directory-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Vincent Tence <vte...@videotron.ca>
Subject Re: [authx] Help with complicated authorization
Date Sat, 18 Jun 2005 17:31:10 GMT
On Fri, 2005-06-17 at 11:05 -0700, Richard Wallace wrote:
> Hello everybody,
> 
> I'm working on pushing our web development from PHP to Java at work.  
> For the moment I've pretty much decided on using JSF/Spring/Hibernate at 
> our presentation/business logic/persistence layers, though I think 
> they're separated well enough that changing out one part of it shouldn't 
> impact any of the others (except in the glue code).

We've embarked on a very ambitious project at work with Tapestry +
Spring and Hibernate 3. I've used JSF over the last year and so far my
experience with Tapestry is much better. If you can, check it out.
There's a great book written by HLS - Tapestry in Action - to get you
going. I really like the way Tapestry preserves you're HTML, which makes
it easy to collaborate with UI design teams. JSF was awful in that
respect.

> Anyways, I'm trying to figure out how to do authorization.  
> Authentication is pretty simple I think, but the authorization is pretty 
> complex.  Instead of a user having or not having permission to access a 
> page (container webapp security) or having or not having permissions to 
> run certain actions (JAAS), we need finer grained permissions based on 
> objects and the users relationship to the object.

As Alex said, that's the kind of problem AuthX aims to solve.

<snip/>

> I'm wondering how I might implement this with AuthX.  Do I simply create 
> custom permissions classes, like ProjectPermission and TaskPermission?  
> Then, when implementing the implies() method what do I do?  Is that 
> where I would do these checks to see if the user has the required 
> ability to do the desired operation?

Correct. You need to create custom Permission classes. The implies()
method is used for granting/denying a permission by comparing the
requested permission with the granted one. There's an example of that in
the authx example app - look for the PurchasePermission.

Let me try to explain. Suppose you decide to grant the permission to
access a task to anybody that has the permission to access the project
owning the task. In this case, you could code your ProjectPermission so
that it implies any permission to access a task of the same project:

(pseudo code)
ProjectPermission {

   ProjectPermission(Project project) {...}

   boolean implies(Permission other) {
	// suppose other is a task permissiom
	task = ((TaskPermission) other).getTask();
	return project.owns(task); // only grant if task belongs to project
   }
}

In XML you would grant your subject with the ProjectPermission, lets
say:

<policy>
    <grant>
        <subjects>
            <username>Rich</username>
        </subjects>
        <permissions>
            <project>Rich's Project</project>
        </permissions>
    <grant>
</policy>

At runtime, when someone tries to access a task, you build a task
permission:

    taskPermission = new TaskPermission(task)

and check if access is authorized:

    authorizer.renderDecision( subject, taskPermission )

The rule engine will check if the subject is Rich and if it is the case,
will see that Rich has the ProjectPermission and will check if this
permission implies the TaskPermission. If the task belongs to Rich's
Project, access will be granted.

That's somewhat simplified, but I hope you get the idea.

> think I'm a little lost because of all the groovy stuff.  Does anyone 
> have an example app that I can work from that doesn't have groovy?

AuthX introduces a rule based system to implement authorization. Rules
are much more flexible than what you can do with an RBAC system. In fact
a rule is anything that implements the Rule interface (no surprise
here):

Rule {
    void evaluate(AuthorizationRequest request);
}

It's very easy to implement RBAC using AuthX rule mechanism. It's a
matter of defining a set of rules that authorize access to a resource if
a subject has a given principal - in this case, a specific
RolePrincipal. But you can do much more with rules. 

The way you define your rules is pluggable in AuthX, and 2 mechanisms
are provided out-of-the box.

1. The first one is to use an XML document. The XMLRuleSetBuilder
provided by AuthX will be parse and interpret your XML document, which
means it neds to know how to deal with the XML elements. A set of XML
elements are understood out of the box, such as:

<grant>, <deny>, <any>, <none>, <username>, <role>, <group>,
<and>,
<or>, ... and you mix them to express your authorization logic.

Furthermore, you can plug your own element interpreters to
XMLRuleSetBuilder. This is useful to represent your permissions, which
are typically application dependent. In your case, you would introduce 2
builders to define elements like <project> and <task> that represent
your project and task permission.

XML is fine, but it lacks the power of expressing more complicated needs
and for every XML element you introduce, there need to be an interpreter
that undertansa it's meaning. That is somewhat limitating and AuthX
wants to support of wide range of authorization systems.

This is where the scripted rules comes into play. 

2. Using groovy (in the future, we could support other scripting
languages, such as rhino, beanshell, pnuts, ...) to define rules is much
more powerful. Just implement the rule interface and code what you need.
I believe this is the best way to allow any kind of logic to be plugged
into the authorization subsystem.

For example, if we want to grant any permissions to canadian people, we
would write it like this in XML:

<policy>
    <grant>
        <subjects>
            <group>canadians</group>
        </subjects>
        <permissions>
            <any/>
        </permissions>
    <grant>
</policy>

And like this in groovy:

class GrantCanadiansAnythingRule {

    evaluate( request ) {
        canadians = new GroupPrincipal("canadians")
        if (request.getSubject().getPrincipals().contains(canadians))
            request.grant()
    }
}

Using a scripted language is much more powerful than using XML.
Furthermore, you could well define your own domain specific language,
write the script interpreter for it and let your security officers write
their security rules themselves. Ok maybe you would just dream of doing
it ;-)

If we come back to our project example above, you could well use a
groovy rule to give access to any project manager to his own projects
tasks:

// pesudo code
class GrantProjectManagerAccessToTheirProjects {

    GrantProjectManagerAccessToTheirProjects( ProjectManagerRepository
repository )

    evaluate( request ) {
        subject = request.getSubject()
        projectManagers = new GroupPrincipal("Project Managers")

        // This rule only applies to pm
        if (!subject.getPrincipals().contains(projectManagers)) return 

        // This rule only applies to task permissions
        if (!(request.getPermission() instance of TaskPermission))
return

        // Ok so this guy is a project manager, get it from the repo
        Set usernames = subject.getPrincipals(UsernamePrincipal.class);
        // in general, there will be one username in the set
        manager = repository.getProjectManager(username)

        // iterate over the list of projects of the manager to see if
the task
        // is in one of them
        task = request.getPermission().getTask()

        projects = manager.ownedProjects()
        for ( each p in projects ) {
                if (p.owns(task)) {
                    request.grant()
                    return
                 }
        }
        request.deny()
    }
}

What's interesting to note here, is that you can use Dependency
Injection with your rules - currently AuthX support CI using
PicoContainer, but support for other containers is possible. In the
example, your DI container would provide the ProjectManager repository.

I hope it helps understand the reasoning for having scripted rules. You
can have a look to the example application in the source tree. It's a
simple web app that demonstrates the concepts of AuthX, using both XML
rules and groovy rules.

If anything else, I'll be happy to answer any question you might have.
We have a very important project at work that has started over 2 months
ago and I'm in charge. It has drained almost most of my freetime and I
don't see it changing before the end of the summer. I'm sorry I've not
been available at all for a long time. Nevertheless, I have resumed
working on AuthX recently. What are the things you would like to see
implemented? That'll help prioritize the backlog. I was thinking of
working on the Hibernate authenticator using Hibernate next. WDYT?

-- Vincent




Mime
View raw message