What
...
Types of Authorization Are Available and Where Can Authorization Take Place
There are many different ways of doing authorization with Ceptor - ranging from simple role-based authorization checking in the Ceptor Gateway before a request is allowed to continue over centrally configured attribute-based checking to complete custom scripts which can implement any kind of checking they wish based upon the available information about the user, his roles, the resource he is attempting to access, and the data he is accessing it with.
Authorization checking can be completely customized by implementing your own Validation code (see Creating a custom Custom Agent Validator for details) which allows complete control over checking group memberships.
...
- Authorization checking can be done before the application is called, e.g. by the Ceptor Gateway
- It can also be done within an application server, before the application logic is called - see Application Server Integrations - decisions might be based upon deployment descriptors, policies etc. depending on what application server is used and what level of authorization it offers.
- It can also be done inside the application either by a filter (e.g. Servlet Filter) which intercepts the call before the application logic is invoked, or it can be done inside the application by specifically doing access checking.
- When done by the application, it can be via standard techniques like
HttpServletRequest.isUserInRole()
,Principal.isInRole()
etc. where Application Server Integrations is used. - ... or it can be done by calling the Ceptor Agent API directly, e.g.
Agent.getInstance().isMemberOfGroup()
,Agent.getInstance().isURLAllowed()
orAgent.getInstance.checkPermission()
- When done by the application, it can be via standard techniques like
RBAC (Role-Based Access Control)
Role-based access control is the concept where a user has zero or many roles attached to him. Resources are protected by roles, and if the user has one of the require required roles, access is allowed, otherwise access is denied to the given resource.
...
Default "magic" roles that exists exist and are used in Ceptor are:
- pp_everyone
Every user/session has this role - no matter if they are authenticated or not - this can be used to allow unrestricted access, or to require that a request has a valid session (anonymous or authenticated) and deny requests without one. - pp_identifiedusers
Only identified users have this role - but no matter how they are authenticated, and what authorization level they have, they have this role automatically. Use this role to protect access to resources where you do not care who the user is or what rights he havehas, but only need him to be authenticated using any available Authentication Plugin (see Authentication Plugins) - pp_anonymous
Only users which are NOT identified have this role - meaning only uses which are not currently logged on.
...
To simplify protecting access to resources, Ceptor allows you to embed additional information into the group name - this functionality is provided by the default Agent Validator (see Creating a custom Custom Agent Validator) and might differ if you use a different authenticator.
...
- <group name>
This is a plain check for group membership - nothing fancy here - the user is member of the group. or he isn't. - <group name>.<authentication level>
In addition to being member of this group, the user needs the minimum<authentication level>
specified - this is determined upon authentication by the Authentication Plugin. It is a plain number. In general, the higher the number the more secure it is and the more trust we have in the user being who is claims to be. - <group name>@<environment>
When applications are accesssaccess, they can optionally be accessed from different environments - e.g. if you have multiple clusters of Gateway's where some are accessed by employees, others by partners or even others by customers, each can be configured with its own environment ID. If you only wish to allow access to a shared application for identified users where the request originates from a specific environment, you can add the environment ID to the group name here. - <group name>.<authentication level>@<environment>
This is a combination of the two above - requires group membership, with a minium minimum specified authentication level and the request needs to have passed through a particular environment.
...
An ACL might have a number of data policies attached to it that is used for Attribute-Based Access Control (ABAC) or it might only be a simple ACL with simple group membership.
...
A user that has one of the groups listed and fulfill the fulfil the data policies that might be attached to the ACL is considered to have access to the resource behind the named ACL.
...
Note that the view of DataPolicyEntry
above is somewhat simplified - in reality, it contains several more attributes such as java class/methods names, C program / function names etc. that are used depending on what policy implementations are in use.
ABAC (Attribute-Based Access Control)
Attribute-Based Access Control or ABAC differs from RBAC in the sense that access decisions are based upon attributes, it can be anything from department or job function to haircolor, shoesize or time of day.
...
With traditional RBAC, the customer has access to the /transfer
url, resource or ACL - or he has not - so it is a yes/no decision based upon group membership.
With ABAC, the customers customer's access might depend upon which account he transfers from, what account he transfers to and what amount he is transferring - it might even depend on his daily limit so it depends on previous actions during the day
DataPolicyEntry: ScriptAuthorization
Below, is a small example of configuration for the Config Based Authorization Plugin where it is configured with a small ACL - this adds a DataPolicyEntry
instance, namely the ScriptAuthorization
to the ACL.
Code Block |
---|
<property name="acl.1" value="sample;execute=pp_everyone;write=staff,admin" description="Sample ACL definition"/>
<property name="acl.json.1" value="{"expectedaccount": "12345"}" description="Attach policy information to this ACL"/>
<property name="acl.script.1" value="%{script}if (context.hasGroupMembership() && context.user.getStateVariable('account') == claim.get('expectedaccount'))
true;
else
false;" description="Attach a datapolicy script to this ACL"/> |
Here, the ACL sample
is defined, and everyone has execute
access, but only admin
and staff
roles have write access.
In addition to the role checking, this script has both a JSON document with policy data information, and a script attached. The script is executed when the policy is evaluated.
The script is called with two variables initialized; context
which is in instance of the ScriptContext
object, and claim
which can get individual attributes out of the attached JSON policy data context object.
This is the object that the script has access to, it must return true, false or null depending if it grants, denies or abstains from granting access.
Code Block | ||
---|---|---|
| ||
public class ScriptContext { public static final String RESULT_DENIED = "true"; public static final String RESULT_GRANTED = "false"; public static final String RESULT_ABSTAIN = "null"; /** Agent instance */ public IAgent agent; /** Session ID */ public String id; /** Data Context */ public IDataContext context; /** ACL entry */ public ACLEntry ae; /** Data Policy Entry */ public DataPolicyEntry dpe; /** Permission Entry */ public PermissionEntry pe; /** Group name */ public String group; /** Data */ public Object data; public boolean hasGroupMembership() throws PTException { return agent.isMemberOfGroup(id, group); } } |