views:

72

answers:

2

I used Java EE 6 with Glassfish v3.0.1, and I wonder if Java EE security model support ACL, and if so how fine-grained is it get?

EDITED
I implement Security using jdbc realm via glassfish v3, that the realm at runtime look into table USER inside the database to check for authentication, by looking at the password field and authorization by looking at the role field. The roles field only contain 2 either ADMINISTRATOR or DESIGNER. So it is a One-to-one map between user and role. At the managed bean level, I implemented this

private Principal getLoggedInUser()
{
    HttpServletRequest request =
            (HttpServletRequest) FacesContext.getCurrentInstance().
                getExternalContext().getRequest();
    if(request.isUserInRole("ADMINISTRATORS")){
        admin = true;
    }else{
        admin = false;
    }
    return request.getUserPrincipal();
}

public boolean isUserNotLogin()
{
    Principal loginUser = getLoggedInUser();
    if (loginUser == null)
    {
        return true;
    }
    return false;
}

public String getLoginUserName()
{
    Principal loginUser = getLoggedInUser();
    if (loginUser != null)
    {
        return loginUser.getName();
    }
    return "None";
} 

by calling isUserInRole, I can determine if the user is admin or not, then the JSF will render the content appropriately. However, that is not fine-grained enough (real quick background info: There are multiple projects, a project contains multiple drawings). Because if u are a DESIGNER, you can see all the drawings from all the projects (what if I only want tom to work on project A, while peter will work on project B, Cindy can supervised over the two project A and B). I want that, at runtime, when I create the user, I can specifically set what project can he/she see. Is there a way to accomplish this? NOTE: There are more than just two projects, the above example is just for demonstration.

+3  A: 

The JEE security model athenticates a 'Principal' which may one have or more 'Roles'.

In the other dimension you have services and resources which need configurable 'Permissions' or 'Capabilities'.

In the configuration you determine which 'Principals' or 'Roles' have which 'Permissions' or 'Capabilities'.

In other words, yes it supports ACL and it is as fine grained as you want it to be, but you'll have to get used to the terminology.

In the answer of Vineet is the excellent suggestion to create 'roles' per project id. Since people must be assigned to projects anyhow, it is straightforward to to add the people to these groups at that time. Alternatively a timed script can update the group memberships based on the roles. The latter approach can be preferable, because it is easier to verify security if these decisions are in one place instead of scattered all over the administration code.

Alternatively you can use "coarse-grained" roles e.g. designer and make use of the database (or program logic) to restrict the views for the user logged in

SELECT p.* FROM projects p, assignments a WHERE p.id = a.projectId AND a.finishdate < NOW();

or

@Stateless class SomeThing {

    @Resource SessionContext ctx;

    @RolesAllowed("DESIGNER")
    public void doSomething(Project project) {
        String userName = ctx.getCallerPrincipal.getName();

        if (project.getTeamMembers().contains(userName) {
            // do stuff
        }
    }

}

Note that the coarse grained access control has here been done with an annotation instead of code. This can move a lot of hard to test boilerplate out of the code and save a lot of time.

There are similar features to render webpages where you can render parts of the screen based on the current user using a tag typically.

Also because security is such a wide reaching concern, I think it is better to use the provided features to get at the context than to pass a battery of boolean flags like isAdmin around as this quickly becomes very messy. It increases coupling and it is another thing making the classes harder to unit-test.

In many JSF implementations there are tags which can help rendering optional things. Here is are examples for richfaces and seam:

<!-- richfaces -->
<rich:panel header="Admin panel" rendered="#{rich:isUserInRole('admin')}">
  Very sensitive information
</rich:panel>

<!-- seam -->
<h:commandButton value="edit" rendered="#{isUserInRole['admin']}"/>.

Here is an article explaining how to add it to ADF

Peter Tillemans
I wrote some codes using jdbc realm for security, but it only utilize `Principal`, I dont know how to use `Permissions` and `Capabilities`, do u think I can post some codes, and ask for your expert opinion?
Harry Pham
This will always help, if not from me, then from more knowledgeable people here.
Peter Tillemans
I just updated my post. If you dont mind, please guide me. Thank you so much
Harry Pham
seems like your first solution is to create a table of `ASSIGNMENT` that has `userId` and `projectId` attributes telling which projects a particular user is assigned. I think that a great idea, I actually have the same thought. They reason I pass boolean `isAdmin` around, is sot that I can use JSF `render` attribute to determine if I should display the component or not. @RolesAllowed, disallow certain user from access certain method, but I think I still have to use boolean `isAdmin` unless you have a better way to render component base on role.
Harry Pham
I added a couple of examples I saw for getting the role from the context rather than passing it as a parameter. YMMV
Peter Tillemans
+2  A: 

The Java EE security model implements RBAC (Role Based Access Control). To a Java EE programmer, this effectively means that permissions to access a resource can be granted to users. Resources could include files, databases, or even code. Therefore, it is possible to not only restrict access to objects like files and tables in databases, it is also possible to restrict access to executable code.

Now, permissions can be grouped together into roles that are eventually linked to users/subjects. This is the Java EE security model in a nutshell.

From the description of your problem, it appears that you wish to distinguish between two different projects as two different resources, and therefore have either two separate permission objects or two separate roles to account for the same. Given that you already have roles (more appropriately termed as user groups) like Administrator, Designer etc. this cannot be achieved in quite easily in Java EE. The reason is that you are distinguishing access to resources to users in a role, based on an additional property of the resource - the project ID. This technically falls into the area known as ABAC (Attribute Based Access Control).

One way of achieving ABAC in Java EE is to carry the properties/attributes granted to the role, in the role name. So instead of the following code:

if(request.isUserInRole("DESIGNERS")){
    access = true;
}else{
    access = false;
}

you ought to doing something like the following. Note the ":" character used as a separator to distinguish the role name from the accompanying attribute.

if(request.isUserInRole("DESIGNERS"+":"+projectId)){
    access = true;
}else{
    access = false;
}

Of course, there is the part where your login module should be modified (either in configuration or in code) to return Roles containing project IDs, instead of plain role names. Do note that all of these suggested changes need to reviewed comprehensively for issues - for instance, one should be disallowing the separator character from being part of a role name, otherwise it is quite possible to perform privilege escalation attacks.

If implementing the above proves to be a handful, you could look at systems like Shibboleth that provide support for ABAC, although I've never seen it being used in a Java EE application.

Vineet Reynolds
So if the `Designer` have permissions to multiple project then I guess it require a bit of parsing, but I guess that is not a big deal. But I am not sure if I understand when you talk about `privilege escalation attacks`. I thought that the role name support to look like this: `DESIGNERS:1234`, but then u said that ` one should be disallowing the separator character from being part of a role name`. Can u please elaborate on that?
Harry Pham
If you are allowing for creation of roles via the application, then it becomes important to ensure that the role names do not contain special characters (in this case the separator). For example, if the internal role name (with project ID) is DESIGNERS:1234, then if you allow for construction of role name with that name, but having access to project 5678, then the internal role name would be DESIGNERS:1234:5678. Depending on how the application is coded, it might be possible to gain access to a person in such a role to gain access to the 1234 project, thus achieving elevation in privileges.
Vineet Reynolds
got it. Thank you, I will keep that in mind
Harry Pham
@Harry, if you do intend to build this, keep in mind that you would be constituting a minuscule minority of people who've gone with this approach. I would recommend that you look at a Off-The-Shelf solution like Spring Security (if you can do away with Java EE based access control), jGuard or Shibboleth. The privilege escalation attack is one of the possible attacks that I could think of, but it need not be the only one.
Vineet Reynolds
And do take a look at the IBM developerWorks article at http://www.ibm.com/developerworks/websphere/techjournal/0710_pattcorner/0710_pattcorner.html, which addresses a problem similar to yours.
Vineet Reynolds
when I research around, I ran into that article but since it is 2007, so I discarded. Plus, i refer to Acegi framework, which is Spring security nowaday. But I read many place that Spring security is not really fit with Java EE. What do u think? Here is the post that I read talking about Java EE and Spring Security: http://stackoverflow.com/questions/2244819/framework-like-spring-security-for-java-ee
Harry Pham
Well, any approach to resolve this issue will either require a solution that builds on top of the Java EE security model or work around it. It is true that when you use Spring Security, you should discard the Java EE model, but if that fits well into your domain and the solution for it, it is preferable to adopt it rather than fight the Java EE model.
Vineet Reynolds
When u said Java EE model, u mean the security model or u mean the framework, that we need to discard the framework and use another type of framework?
Harry Pham
I'm referring to the model. While you can continue to use JSF and EJB, support for ACLs could be incorporated using a different security framework that fits well with your requirements. Be forewarned that some amount of re-designing might have to be done.
Vineet Reynolds