Mosaic 9.5 has allows control of content based on authorization rules stored in a policy file. This means we can control access to an application, catalog, tile or other resource by setting permissions in the policy file. We can also combine the permissions in different ways to control the user experience.
This is a very powerful feature that allows the developer or administrator to control resource access at a very fine grained level. It also can be an incredibly maddening feature when it is not configured properly. In this post I’ll try to demystify some of the magic behind authorization. Hopefully this will make your configuration a bit less stressful.
The rules for the authorization of Mosaic content is stored in a policy file which is deployed to Mosaic as you would other resources. The application and catalog descriptors will have a Policy Reference that indicates what policy file(s) contain the rules for the resource. The policy reference is optional, and if it is absent it means that there are no specific rules for that resource. There may be more than one policy file deployed to your server.
The policy file uses the OASIS eXtensible Access Control Markup Language (XACML) notation to define the authorization rules for each resource. This allows you to set up some incredibly complex rules for authorization, but it also allows you to get a little too creative with the rules. Its like juggling chainsaws. Its really cool when it works, but if something goes wrong there will be a big mess to clean up.
The rules of authorization:
These are some general rules of thumb that will help you keep the authorization functionality from driving you crazy:
- Mosaic evaluates the authorization at runtime.
When a user accesses an application, Mosaic reads the application descriptor and assembles the application before sending it to the client. While this allows you to update rules with out recompiling code, it also means that large, complex policy files can cause performance issues.
- The evaluation of permissions for each resource is independent of that for other resources.
When Mosaic determines that a resource is needed, it checks the policy file to see if the user has access (assuming there is a policy reference). Then the next resource is similarly checked. Mosaic does not maintain state information between the calls, so each resource request is judged on its own merits. For example, say a tile is used by two different applications. The tile rules are evaluated separately from the evaluation of the applications. In other words; If you can read a tile, you can read that tile regardless of what application it is in.
- If a resource is inside of another resource, you need access to the parent resource as well.
Although each resource is evaluated on its own, for practical purposes, there is a evaluation order. You can consider the evaluation order as application, catalog, view template, panel template and tile (or other catalog resource) and that these can be treated as an AND operation.
What that means is that if you have access to the tiles and not access to the app, you won’t see anything. Although the tile rules may say you have read access, the tiles have no container into which they can be put.
For example; to see a tile the user must have access to the application AND the catalog AND the tile (1&1&1=1). If any of these are denied, you will not see the tile.
In addition, there are two corollaries to the rules:
- What happens if there is no policy?
This can happen if the resource (application, catalog, tile, etc.) has no policy file reference. Since there is no rule, Mosaic assumes access is granted.
- What happens if there is a policy, but no rule applies?
This can happen if there is no specific rule in the policy that applies to the resource for that user. According to the XACML standard, this results in an indeterminate result. In this case Mosaic falls back to the overall Mosaic authorization setting (also known as the base setting). This is set in the mosaic-context.xml file using the denyWhenIndeterminate property. If the value is set to true then any indeterminate requests will be denied.
One thing to watch for is an error in your XACML policy file. If there is a mistake or typo that is still legal XACML, an indeterminate state can be returned. For example, if you make a mistake in an attribute entry then the rule may not execute and an indeterminate result will be returned. If the denyWhenIndeterminate property is set then no user will be able to access the resource.
For these reasons I recommend adding a “catch all” rule that will apply when no others do. It will make debugging your policy file much easier.
Lets take a look at a simple sample to see how this works. The source for this example can be downloaded here.
The test consists of the following:
· Two user roles were added to Mosaic. Each role has one unique user:
o <security:user name=”r1″ password=”password” authorities=”ROLE_MOSAIC_R1″/>
o <security:user name=”r2″ password=”password” authorities=”ROLE_MOSAIC_R2″/>
· Two applications – App1 and App2
· One catalog – AppCatalog
· Two tiles – Tile1 and Tile2
· AppCatalog has entries for Tile1 and Tile2
· App1 uses Tile1 and Tile2 from the AppCatalog
· App2 uses Tile1 and Tile2 from the AppCatalog
· There is one policy file – ControlPolicy
· App1 and App2 contain a reference to ControlPolicy
· AppCatalog contains a reference to ControlPolicy at its root
· The Tile1 and Tile2 entries in the AppCatalog each contain a reference to ControlPolicy
When the applications are accessed using the owner’s account (a super user with all access granted) they look like the following:
App1 with no authorization rules:
App2 with no authorization rules:
Rules for R1:
· Read access for App1
· Read access for AppCatalog
· Read access for Tile1
Rules for R2:
· Read access for App2
· Read access for AppCatalog
· Read access for Tile2
Rules for resource owner:
· All actions to all resources
In addition there is a “catch all” rule to catch anything that does not apply to the above. This rule is set to deny.
The following are the results when the two users attempt to access the two applications with the above listed rules:
For user R1:
· When accessing App1, user R1 sees the app and Tile1. He does not see Tile2
o The user has access to the app, the catalog and Tile1 (1&1&1=1) so he sees Tile1
o The user has no access to Tile2 (1&1&0=0) so he does not see Tile2
· When accessing App2, user R1 is denied access.
o The user has no access to the app, but does have access to the catalog and Tile1. Since he can’t see the app, access to the catalog and tile are not relevant (0&1&0=0)
For user R2:
· When accessing App1, user R1 is denied access
· When accessing App2, user R2 sees only Tile2. He does not see Tile1
What happens if you want to do more complex rules on combinations of resources? As I said earlier, Mosaic requests authorization on individual resources and does not pass the state information during the request. If you want a combo – say only show Tile 2 if Tile 1 is present – can you do it? You can, but you need to be a bit creative.
You need to find a way to combine the two tiles into a single resource on which Mosaic can check the authorization. Fortunately, this can be easily done using view and panel templates. In the catalog you can combine the tiles you need into a single view/panel. The application will reference the view/panel template and not the tiles individually. The policy file will include a resource entry for the view/panel as well as the tiles, catalog and application.
Of course the rules must be setup so the user has access to the tiles as well as the view/panel.