ory/ladon

add support for Tarantool

Closed this issue · 24 comments

feel free to create a PR

i'm still not strong enough at this area - golang. but i will try :)

still trying to figure out how to protect our rest api with oauth :) and maybe ladon, instead of common rbac

  1. what subset of regexp can be used for: subjects, actions?
  2. rethink-db manager caches policies in memory, but postgres manager - not. Why?

I'm working on tarantool manager and can't decide what way to choose. From one side it's in memory db, so no need to have another copy in memory, from other side i can't use regexp to search in tarantool directly.

  1. what subset of regexp can be used for: subjects, actions?

There's no limitation. Regex is compiled using go native libraries, so check that out for special modifiers etc.

  1. rethink-db manager caches policies in memory, but postgres manager - not. Why?

Because postgres does not support pub/sub :)

I'm working on tarantool manager and can't decide what way to choose. From one side it's in memory db, so no need to have another copy in memory, from other side i can't use regexp to search in tarantool directly.

Postgres and RethinkDB are fast as well, the real issue is network latency. Depending on your environment, network roundtrips to the database can significantly reduce performance. As access control is executed on every request (sometime even multiple times) this should be really fast. Then again, if you only serve 50 requests per minute it shouldn't be a big deal.

i need low latency.

hmm...maybe i miss something, but manager has 'create' method, so why not to reset stored in 'memory' policies that were updated?

If you need low latency, you probably need scaling as well. You can not scale in-memory databases without some sort of pub/sub. Otherwise one instance will insert data and update the local cache, but the other instance won't notice

let's consider case when no horizontal scaling is required (not current case), but i still need low latency, because of: "As access control is executed on every request (sometime even multiple times) this should be really fast."

i would like to put 'scaling' to the shoulders of storage. Right now i worry about latency. But if full set of regexp can be used, then looks like i can't move this to tarantool totally :( still need cache in memory :(

What about failover? What if regex is the real bottleneck, not storage? If you have the opportunity to developing a new system, anticipate the hurtles of running it too. 20% is development, 80% is running it.

Why not take the short route and simply use postgres or rethinkdb as a backend? With AWS, Heroku, Cloud Foundry, Azure and all these other services it shouldn't be a big deal :) Both postgres and rethink support are well tested (in production)!

If you want to stick to tarantool you could add a very simple cache with TTL. If cache is older then 10 minutes or the requested element could not be found poll the database, compute regex, reset TTL and serve the request.

because we are considering tarantool as our application server in future. But i see you. Tarantool uses lua, so no regexp. Probably i will just recreate 'ladon' as package for tarantool pure in lua

I see. If I may give some advice here: Choose a diverse ecosystem based on use cases, but isolate the environments. Sticking to one technology because it solves one problem well, should not impose the use of this technology for a different set of problem :)

I once wrote a system backed by a RDBMS. It made a lot of sense because it was a highly relational business logic. However, part of the system was organized as a directed graph. I decided to not use Neo4J or similar technology because we already had MySQL. Two years later, that tree takes up to 5 minutes to render due to its recursive nature. Because everything is so tightly coupled now, I can not replace that part and we're stuck with it until we rewrite the whole thing.

I can not speak for your enterprise because I don't know it. Maybe it makes sense to use one application server but more likely it doesn't. :)

Anyways, I think you could make ladon work with tarantool by introducing a local cache-layer that has a short TTL.

By the way, LUA supports regex, If there's LUA support in queries, there should be regex support as well.

By the way, check out hydra. Hydra uses ladon for access control so it might just be what you need to get started. You can replace Hydra later on with your own solution easily, but it saves you the headaches of solving access control yourself in the early phase.

yeah, i saw hydra already :) but looks like right now i'm not ready for it :) i want just simple 2 things: api and protect it with oauth2 :) in our case we will have api-centric architecture, mostly no access from outside (at least right now), but some day probably we will need access from mobile application - that's why i would like to protect with more mature solution like oauth2, instead of plain cookie :))))

hydra is exactly for the use case:

api and protect it with oauth2 :)

if you want help understanding what hydra is and does and how to use it, ask on gitter or the mailinglist :)

thanks, will check :) in our case we need solution that will work with differ storages (not always RDBMS), that why we are moving to independent application server as separate component. We can't say: ok, for api we will use postgres, for your data we will use oracle :( but we can say, ok our system has application server as tarantool, for your data - oracle, postgres, whatever

Ahhh I see, that makes a lot of sense :)

But i still would like to use ladon :) so last question - i would like to replace IsAllowed, because in case of tarantool i would like to move 'matching' to server as stored proc and at go side checks only for conditions of matched policies.

Why ladon? because in some cases we can be forced to use specific RDBMS and i would like to stick to one solution for auth.

You're probably looking for this then: https://github.com/ory-am/ladon/blob/master/ladon.go#L75

yep, i know. but there is no interface :) i was talking about that :)

Ah I see. The way to solve this would be:

type Matcher func(p Policy, haystack []string, needle string) (bool, error)

type Ladon struct {
    Manager Manager
    Matcher Matcher
}

Now you can initialize Ladon with any matcher that implements the Matcher signature.

i still would like to override IsAllowed, because i will move it to lua at tarantool, so my way will be:

func (g *Ladon) IsAllowed(r *Request) (err error) {
    policies, err := g.Manager.FindPoliciesForSubject(r.Subject)
    if err != nil {
        return errors.New(err)
    }

    return g.doPoliciesAllow(r, policies)
}

func (g *Ladon) doPoliciesAllow(r *Request, policies []Policy) (err error) {
    var allowed = false

    // Iterate through all policies
    for _, p := range policies {
        // Are the policies conditions met?
        if !g.passesConditions(p, r) {
            // no, continue to next policy
            continue
        }

        // Is the policies effect deny? If yes, this overrides all allow policies -> access denied.
        if !p.AllowAccess() {
            return errors.New(ErrForbidden)
        }

        allowed = true
    }

    if !allowed {
        return errors.New(ErrForbidden)
    }

    return nil
}

and at FindPoliciesForSubject i would like also check for actions and resources

btw: Why do you check for subjects second time at doPoliciesAllow?

Sure you can do that, simply implement a new struct like LadonTarantool.

btw: Why do you check for subjects second time at doPoliciesAllow?

Just in case the manager regex works differently from go regex.

looks like for our case it will not use ladon in most cases, so can be closed.

Because postgres does not support pub/sub :)

I begg to differ https://www.postgresql.org/docs/9.5/static/sql-notify.html

(after maybe it does not cover your use case)

Nice!