17 The Security Model
This chapter includes the following sections:
- About the OPSS Authorization and Policy Models
- Authorization Models
- The JAAS/OPSS Authorization Model
Parent topic: Developing with OPSS APIs
About the OPSS Authorization and Policy Models
For information about the OPSS authorization and policy models, see Administering Oracle Entitlements Server.
Parent topic: The Security Model
Authorization Models
A policy specifies the permissions granted to code loaded from a given location. The JAAS model extends policies by allowing an optional list of principals. These policies grant permissions to code from a specified location that is run by any of those principals.
The OPSS model is based on the JAAS model and, moreover, allows application policies and roles, and system policies. Application roles can be mapped to enterprise users and groups (such as administrative roles). A policy can grant permissions to any of these roles, groups, or principals.
A Jakarta EE application can delegate authorization to the container where it runs,
or it can implement its own authorization with calls to methods such as
checkPermission
, checkBulkAuthorization
, or
getGrantedResources
.
The following sections describe the main points of the Jakarta EE and JAAS authorization models:
The Jakarta EE Authorization Model
The Jakarta EE authorization model uses role membership to control access to Jakarta Enterprise Beans (EJBs) and web resources that are referenced by URLs. Policies assign permissions to users and roles, and they are enforced by the container.
In the Jakarta EE model, authorization is implemented in either of the following ways:
-
Declaratively, where policies are specified in deployment descriptors. The container reads those policies from deployment descriptors and enforces them. No special application code is required to enforce authorization.
-
Programmatically, where policies are processed in application code. The code checks whether a subject has the appropriate permission to execute specific sections of code. If the subject fails to have the proper permission, then the code throws an exception.
Table 17-1 shows the advantages and disadvantages of each approach.
Table 17-1 Comparing Authorization in the Jakarta EE Model
Authorization Type | Advantages | Disadvantages |
---|---|---|
Declarative |
No coding needed. Easy to update by modifying just deployment descriptors. |
Authorization is specified at the URL level or at the EJB method level. |
Programmatic |
Specified in application code. Provides fine-grained authorization. |
Not so easy to update, because it involves code changes and recompilation. |
A container can provide authorization to applications running in it in two ways: declaratively and programmatically, as explained in the following sections:
Parent topic: Authorization Models
Declarative Authorization
Declarative authorization allows you to control access to URL-based resources (such as Java servlets and pages) and EJB methods.
To configure declarative authorization:
-
Specify (in standard deployment descriptors) the resource to protect and a role that has access to that resource. Alternatively, use code annotations.
-
Map the role to an enterprise group (in proprietary deployment descriptors, such as the
web.xml
file).
Parent topic: The Jakarta EE Authorization Model
Programmatic Authorization
Programmatic authorization provides a fine-grained authorization not available in declarative approach, and it requires that the application code call the isUserInRole
method (for Java servlets) or the isCallerInRole
method (for EJB), both available from standard Java APIs.
Although these methods still depend on role membership to determine authorization, they give finer control over authorization decisions because the controlling access is not limited to EJB or URL.
Parent topic: The Jakarta EE Authorization Model
Jakarta EE Application Example
The following example illustrates an application calling the isUserInRole
method. The example assumes that the application Enterprise ARchive (EAR) file includes the web.xml
and weblogic-application.xml
files, and that these files include the following specifications:
<!-- security roles in web.xml --> <security-role> <role-name>sr_developer</role-name> </security-role>
<!-- maaping of user to role in weblogic.application.xml --> <wls:security-role-assignment> <wls:role-name>sr_developer</wls:role-name> <wls:principal-name>weblogic</wls:principal-name> </wls:security-role-assignment>
Code Calling isUserInRole
import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Date; public class PolicyServlet extends HttpServlet { public PolicyServlet() { super(); } public void init(ServletConfig config) throws ServletException { super.init(config); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final ServletOutputStream out = response.getOutputStream(); response.setContentType("text/html"); out.println("<HTML><BODY bgcolor=\"#FFFFFF\">"); out.println("Time stamp: " + new Date().toString()); out.println( "<br>request.getRemoteUser = " + request.getRemoteUser() + "<br>"); out.println("request.isUserInRole('sr_developer') = " + request.isUserInRole("sr_developer") + "<br>"); out.println("request.getUserPrincipal = " + request.getUserPrincipal() + "<br>"); out.println("</BODY>"); out.println("</HTML>"); } }
Parent topic: The Jakarta EE Authorization Model
The JAAS Authorization Model
The JAAS authorization model introduces permissions but also uses roles. In this model, a policy binds permissions with a subject (role, group, or user) and, optionally, with code. You grant permission to a role by calling the addPrincipalsToAppRole
method. Permissions are evaluated by calls to the static AccessController.checkPermission
method. The model allows a high control of resources.
In a policy you specify the following data:
-
Application roles and enterprise groups allowed the permission(s).
-
Permissions (in application policies) and codesources (in system policies). Application polices define what a user or the member of a group is allowed to access. System policies define what actions the code is allowed to perform.
When you program with this model, you precede sensitive parts of the your application with checks that determine whether the current user or role has the appropriate permissions to the code, and the code is run if the user has the right permissions. For an example, see Using Supported Permission Classes.
Parent topic: Authorization Models
The JAAS/OPSS Authorization Model
JAAS/OPSS authorization is based on controlling the operations that a class can perform when it is loaded and run in the environment.
The following sections explain the OPSS authorization model:
- The Resource Catalog
- Managing Policies
- Checking Policies Programmatically
- The Class ResourcePermission
Parent topic: The Security Model
The Resource Catalog
OPSS supports the specification and runtime support of the resource catalog in security stores.
The resource catalog allows you to:
-
Describe policies and secured artifacts in human-readable terms.
-
Define and modify policies independently of the application source code.
-
Browse and search policies, roles, and the role hierarchy.
-
Group permissions in entitlements.
Parent topic: The JAAS/OPSS Authorization Model
Managing Policies
Manage the resource catalog with the following interfaces, all sub-interfaces of oracle.security.jps.service.policystore.EntityManager
:
-
GrantManager
- Use this interface to query grants using search criteria, to obtain list of grants that satisfy various combinations of resource catalog artifacts, and to grant or revoke permissions to principals. -
PermissionSetManager
- Use this interface to create, modify, and query permission entitlements. -
ResourceManager
- Use this interface to create, delete, and modify resource instances. -
ResourceTypeManager
- Use this interface to create, delete, modify, and query resource types.
To create a resource type, a resource instance, actions, or a permission set, use code like the following:
import oracle.security.jps.service.policystore.entitymanager.*; import oracle.security.jps.service.policystore.search.*; import oracle.security.jps.service.policystore.info.resource.*; import oracle.security.jps.service.policystore.info.*; import oracle.security.jps.service.policystore.*; import java.util.*; public class example { public static void main(String[] args) throws Exception { ApplicationPolicy ap; ResourceTypeManager rtm = ap.getEntityManager(ResourceTypeManager.class); ResourceTypeSearchQuery query = new ResourceTypeSearchQuery(); query.setANDMatch(); query.addQuery(ResourceTypeSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "resourceType", BaseSearchQuery.MATCHER.EXACT); List<ResourceTypeEntry> allResourceTypes = rtm.getResourceTypes(query); ResourceManager rm = ap.getEntityManager(ResourceManager.class); ResourceSearchQuery ResourceQuery = new ResourceSearchQuery(); ResourceQuery.setANDMatch(); ResourceQuery.addQuery(ResourceSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "R2", BaseSearchQuery.MATCHER.EXACT); List<ResourceEntry> allResources = rm.getResources("RT2", ResourceQuery); PermissionSetManager psm = ap.getEntityManager(PermissionSetManager.class); PermissionSetSearchQuery pssq = new PermissionSetSearchQuery(); pssq.setANDMatch(); pssq.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "PS1", BaseSearchQuery.MATCHER.EXACT); List<PermissionSetEntry> allPermSets = psm.getPermissionSets(pssq); RoleCategoryManager rcm = ap.getEntityManager(RoleCategoryManager.class); RoleCategorySearchQuery rcsq = new RoleCategorySearchQuery(); rcsq.setANDMatch(); rcsq.addQuery(RoleCategorySearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "roleCategoryCartoon", BaseSearchQuery.MATCHER.EXACT); List<RoleCategoryEntry> allRoleCategories = rcm.getRoleCategories(rcsq); } }
The following example illustrates a complex query involving resource catalog elements:
//ApplicationPolicy ap as in the preceeding example ResourceTypeManager rtm = ap.getEntityManager(ResourceTypeManager.class); ResourceTypeSearchQuery query = new ResourceTypeSearchQuery(); query.setANDMatch(); query.addQuery(ResourceTypeSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "resourceType", BaseSearchQuery.MATCHER.EXACT); List<ResourceTypeEntry> enties = rtm.getResourceTypes(query); ResourceManager rm = ap.getEntityManager(ResourceManager.class); ResourceSearchQuery ResourceQuery = new ResourceSearchQuery(); ResourceQuery.setANDMatch(); ResourceQuery.addQuery(ResourceSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "R2", BaseSearchQuery.MATCHER.EXACT); ArrayList<BaseSearchQuery> querries = ResourceQuery.getQueries(); List<ResourceEntry> resources = rm.getResources("RT2", ResourceQuery); PermissionSetManager psm = ap.getEntityManager(PermissionSetManager.class); PermissionSetSearchQuery pssq = new PermissionSetSearchQuery(); pssq.setANDMatch(); pssq.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "PS1", BaseSearchQuery.MATCHER.EXACT); List<PermissionSetEntry> psets = psm.getPermissionSets(pssq); RoleCategoryManager rcm = ap.getEntityManager(RoleCategoryManager.class); RoleCategorySearchQuery rcsq = new RoleCategorySearchQuery(); rcsq.setANDMatch(); rcsq.addQuery(RoleCategorySearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "roleCategoryCartoon", BaseSearchQuery.MATCHER.EXACT); ArrayList<BaseSearchQuery> queries = rcsq.getQueries(); List<RoleCategoryEntry> rcs = rcm.getRoleCategories(rcsq);
The following example illustrates how to create a grant:
GrantManager gm = ap.getEntityManager(GrantManager.class); Set<PrincipalEntry> pe = new HashSet<PrincipalEntry>(); List<AppRoleEntry> are = ap.searchAppRoles(appRoleName); pe.addAll(are); gm.grant(pe, null, permissionSetName);
Parent topic: The JAAS/OPSS Authorization Model
Checking Policies Programmatically
When you check policies programmatically, keep in mind the following points:
-
By default, authorization failures are not visible in the console. To have authorization failures sent to the console, set the
jps.auth.debug
system variable:-Djps.auth.debug=true
.In particular, to have
JpsAuth.checkPermission
failures sent to the console, you must set that variable. -
The policy provider must be explicitly set in Java SE applications:
java.security.Policy.setPolicy(new oracle.security.jps.internal.policystore.JavaPolicyProvider())
Not setting the policy provider explicitly in a Java SE application may cause runtime methods (such as
JpsAuth.checkPermission
) to return incorrect values.
The following sections illustrate the use of several methods to check policies programmatically:
- Using checkPermission
- Using doAs and doAsPrivileged
- Using checkBulkAuthorization
- Using getGrantedResources
Parent topic: The JAAS/OPSS Authorization Model
Using checkPermission
Oracle Fusion Middleware supports the checkPermission
method in the java.security.AccessController
and oracle.security.jps.util.JpsAuth
classes.
Oracle recommends the use of checkPermission
in the JpsAuth
class because it provides better debugging support, better performance, and audit support.
The static AccessController.checkPermission
method uses the default access control context (the context inherited when the thread was created). To check permissions on some other context, call the instance checkPermission
method on a particular AccessControlContext
instance.
The following table describes the behavior of checkPermission
according to the value of the JAAS mode:
Table 17-2 checkPermission Behavior According to JAAS Mode
JAAS Mode | checkPermission Behavior |
---|---|
|
Enforces codesource security based on the security policy in effect, and there is no provision for subject-based security. |
|
Enforces a combination of codesource and subject-based security using the access control context created in the |
|
Enforces subject-based security using a null access control context. |
|
Takes into consideration grants involving principals only (and it disregards those involving codesource) when evaluating a permission. |
Note:
If you call checkPermission
inside a doAs
block and the check permission call fails, then to display the failed protection domain you must set the java.security.debug=access,failure
system property.
The following example illustrates an application checking a permission. It assumes that the application EAR file includes the configuration jazn-data.xml
and web.xml
files.
jazn-data.xml
<?xml version="1.0" ?> <jazn-data> <policy-store> <applications> <application> <name>MyApp</name> <app-roles> <app-role> <name>AppRole</name> <display-name>AppRole display name</display-name> <description>AppRole description</description> <guid>F5494E409CFB11DEBFEBC11296284F58</guid> <class>oracle.security.jps.service.policystore.ApplicationRole</class> </app-role> </app-roles> <resource-types> <resource-type> <name>MyResourceType</name> <display-name>MyResourceType display name</display-name> <description>MyResourceType description</description> <provider-name>MyResourceType provider</provider-name> <matcher-class>oracle.security.jps.ResourcePermission</matcher-class> <actions-delimiter>,</actions-delimiter> <actions>write,read</actions> </resource-type> </resource-types> <resources> <resource> <name>MyResource</name> <display-name>MyResource display name</display-name> <description>MyResource description</description> <type-name-ref>MyResourceType</type-name-ref> </resource> </resources> <permission-sets> <permission-set> <name>MyEntitlement</name> <display-name>MyEntitlement display name</display-name> <description>MyEntitlement description</description> <member-resources> <member-resource> <type-name-ref>MyResourceType</type-name-ref> <resource-name>MyResource</resource-name> <actions>write</actions> </member-resource> </member-resources> </permission-set> </permission-sets> <jazn-policy> <grant> <grantee> <principals> <principal> <class> oracle.security.jps.service.policystore.ApplicationRole</class> <name>AppRole</name> <guid>F5494E409CFB11DEBFEBC11296284F58</guid> </principal> </principals> </grantee> <!-- entitlement --> <permission-set-refs> <permission-set-ref> <name>MyEntitlement</name> </permission-set-ref> </permission-set-refs> </grant> </jazn-policy> </application> </applications> </policy-store> <jazn-policy></jazn-policy> </jazn-data>
web.xml
The following example illustrates the JpsFilter
filter configuration:
<web-app> <display-name>PolicyTest: PolicyServlet</display-name> <filter> <filter-name>JpsFilter</filter-name> <filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class> <init-param> <param-name>application.name</param-name> <param-value>PolicyServlet</param-value> </init-param> </filter> <filter-mapping> <filter-name>JpsFilter</filter-name> <servlet-name>PolicyServlet</servlet-name> <dispatcher>REQUEST</dispatcher> </filter-mapping>...
Example
In the following example, Subject.doAsPrivileged
may be replaced by JpsSubject.doAsPrivileged
:
import javax.security.auth.Subject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.*;
import java.util.Date;
import java.util.PropertyPermission;
import java.io.FilePermission;
public class PolicyServlet extends HttpServlet {
public PolicyServlet() {
super();
}
public void init(ServletConfig config)
throws ServletException {
super.init(config);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final ServletOutputStream out = response.getOutputStream();
response.setContentType("text/html");
out.println("<HTML><BODY bgcolor=\"#FFFFFF\">");
out.println("Time stamp: " + new Date().toString());
out.println( "<br>request.getRemoteUser = " + request.getRemoteUser() + "<br>");
out.println("request.isUserInRole('sr_developer') = " + request.isUserInRole("sr_developer") + "<br>");
out.println("request.getUserPrincipal = " + request.getUserPrincipal() + "<br>");
Subject s = null;
s = Subject.getSubject(AccessController.getContext());
out.println("Subject in servlet " + s);
out.println("<br>");
final RuntimePermission rtPerm = new RuntimePermission("getClassLoader");
try {
Subject.doAsPrivileged(s, new PrivilegedAction() {
public Object run() {
try {
AccessController.checkPermission(rtPerm);
out.println("<br>");
out.println("CheckPermission passed for permission: " + rtPerm+ " seeded in application policy");
out.println("<br>");
} catch (IOException e) {
e.printStackTrace();
printException ("IOException", e, out);
} catch (AccessControlException ace) {
ace.printStackTrace();
printException ("Accesscontrol Exception", ace, out);
}
return null;
}
}, null);
} catch (Throwable e) {
e.printStackTrace();
printException("application policy check failed", e, out);
}
out.println("</BODY>");
out.println("</HTML>");
}
void printException(String msg, Throwable e, ServletOutputStream out) {
Throwable t;
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
e.printStackTrace(pw);
out.println("<p>" + msg + "<p>");
out.println("<code>");
out.println(sw.getBuffer().toString());
t = e;
/* Print the root cause */
while ((t = t.getCause()) != null) {
sw = new StringWriter();
pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
out.println("<hr>");
out.println("<p> Caused By ... </p>");
out.println(sw.getBuffer().toString());
}
out.println("</code><p>");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
Parent topic: Checking Policies Programmatically
Using doAs and doAsPrivileged
Oracle Fusion Middleware supports the doAs
and doAsPrivileged
methods in the javax.security.auth.Subject
and oracle.security.jps.util.JpsSubject
classes.
Oracle recommends you use the oracle.security.jps.util.JpsSubject
class because it renders better performance and provides audit.
Note:
If you call checkPermission
inside a doAs
block and the check permission call fails, then to display the failed protection domain you must set the java.security.debug=access,failure
system property.
Parent topic: Checking Policies Programmatically
Using checkBulkAuthorization
The checkBulkAuthorization
method determines whether a subject has access to one or more resource actions. This method returns the set of resource actions the subject is authorized on the resources. Grants using resources must include the resource type.
When you call this method, make sure that:
-
You have set the
java.security.policy
system property to the location of the Oracle WebLogic Server policy file. -
Your application calls
checkBulkAuthorization
aftersetPolicy
:java.security.Policy.setPolicy(new oracle.security.jps.internal.policystore.JavaPolicyProvider())
checkBulkAuthorization
assumes that:
-
The caller can provide a subject with user and enterprise role principals, and a list of resources including the stripe each resource belongs to.
-
The application can access the application stripes configured in the domain where the application is running.
Parent topic: Checking Policies Programmatically
Using getGrantedResources
The getGrantedResources
method provides a runtime authorization query to fetch all granted resources on a given subject by returning the resource actions that have been granted to the subject. This method returns only permissions associated with resource types and is available only when for LDAP security stores.
Parent topic: Checking Policies Programmatically
The Class ResourcePermission
A permission class provides the means to control the actions that a grantee is allowed on a resource. Even though a custom permission class gives you complete control over the actions, target matching, and logic, to work as expected at runtime, a custom permission class must be specified in the system classpath of the server so that it is available and can be loaded when it is required. But modifying the system class path in environments is difficult and, in some environments, such modification might not be even possible.
OPSS includes the oracle.security.jps.ResourcePermission
class that you use as the permission class within any application grant to protect application or system resources. In this way, you no longer need to write custom permission classes and can readily use that class in permissions within application grants stored in any supported policy provider. Do not use this class in system policies, but use it only in application policies.
Configuring Resource Permissions
A permission that uses the ResourcePermission
class is called a resource permission, and it specifies the resource type, the resource name, and an optional list of actions:
<permission> <class>oracle.security.jps.ResourcePermission</class> <name>resourceType=type,resourceName=name</name> <actions>character-separated-list-of-actions</actions> </permission>
Even though the resource type information is not used at runtime, the resource type definition is required.
The following examples illustrate the specifications of resource permissions, which include the required resource types:
<permission> <class>oracle.security.jps.ResourcePermission</class> <name>resourceType=epm.calcmgr.permission,resourceName=EPM_Calc_Manager</name> </permission> <resource-types> <resource-type> <name>epm.calcmgr.permission</name> <display-name>CalcManager ResourceType</display-name> <description>Resourcetype for managing CalcManager grants</description> <provider-name></provider-name> <matcher-class>oracle.security.jps.ResourcePermission</matcher-class> <actions-delimiter>,</actions-delimiter> <actions></actions> </resource-type> </resource-types> <permission> <class>oracle.security.jps.ResourcePermission</class> <name>resourceType=oracle.bi.publisher.Reports,resourceName=GLReports</name> <actions>develop;schedule</actions> </permission> <resource-types> <resource-type> <name>oracle.bi.publisher.Reports</name> <display-name>BI Publisher Reports</display-name> <provider-name></provider-name> <matcher-class>oracle.security.jps.ResourcePermission</matcher-class> <actions-delimiter>;</actions-delimiter> <actions>view;develop;schedule</actions> </resource-type> </resource-types>
A resource type associated with a resource permission can have an empty list of actions. Note the following points about resource permissions:
-
The name must conform to the following format:
resourceType=aType,resourceName=aName
You must define the resource type of a resource permission. To obtain the type of a resource, use the
ResourcePermission.getType
method. -
The character-separated list of actions is optional. If specified, then it must be a subset of the actions specified in the associated resource type. The method ResourcePermission.getActions returns this list.
The character used to separate the items of the list must equal to the character specified in the <actions-delimiter> of the associated resource type.
-
The
ResourcePermission.getResourceName
method returns the display name of a resource used in a permission. -
Wildcard characters are not supported in resource permissions.
Managing and Checking Resource Permissions
The following lines illustrate how to create a resource permission and how to check it:
ResourcePermission rp = new ResourcePermission("oracle.bi.publisher.Reports","GLReps","develop"); JpsAuth.checkPermission(rp);
The permission check succeeds if the resource permission satisfies the following conditions:
-
The permission is an instance of the
ResourcePermision
class. -
The resource type name matches (ignoring case) the name of a resource type.
-
The resource name matches exactly the name of a resource instance.
-
The list of actions is a comma-separated subset of the set of actions specified in the resource type.
About the Class for a Resource Type
When you create a resource type, optionally specify a class. If unspecified, then it defaults to the oracle.security.jps.ResourcePermission
class.
If two or more resource types share a class, then that class must be one of the following:
-
The
oracle.security.jps.ResourcePermission
class. -
A concrete class extending the
oracle.security.jps.AbstractTypedPermission
abstract class, as illustrated byMyAbstractTypedPermission
:public class MyAbstractTypedPermission extends AbstractTypedPermission { private static final long serialVersionUID = 8665318227676708586L; public MyAbstractTypedPermission(String resourceType, String resourceName, String actions) {super(resourceType, resourceName, actions); } }
-
A class implementing the
oracle.security.jps.TypePermission
class and extending thejava.security.Permission
class.
Parent topic: The JAAS/OPSS Authorization Model