7 Authorization Providers

This chapter describes authorization provider concepts and functionality, and provides step-by-step instructions for developing a custom authorization provider.

Authorization is the process whereby the interactions between users and WebLogic resources are controlled, based on user identity or other information. In other words, authorization answers the question, "What can you access?" In WebLogic Server, an authorization provider is used to limit the interactions between users and WebLogic resources to ensure integrity, confidentiality, and availability.

This chapter includes the following sections:

Authorization Concepts

Before you develop an authorization provider, you need to understand the following concepts:

Access Decisions

Like LoginModules for authentication providers, an Access Decision is the component of an authorization provider that actually answers the "is access allowed?" question. Specifically, an Access Decision is asked whether a subject has permission to perform a given operation on a WebLogic resource, with specific parameters in an application. Given this information, the Access Decision responds with a result of PERMIT, DENY, or ABSTAIN.

Using the Java Authorization Contract for Containers

The Java Authorization Contract for Containers (JACC) is part of Java EE. JACC extends the permission-based security model to EJBs and Servlets. JACC is defined by JSR-115 (http://www.jcp.org/en/jsr/detail?id=115).

JACC provides an alternate authorization mechanism for the EJB and Servlet containers in a WebLogic Server domain. When JACC is configured, the WebLogic Security framework access decisions, adjudication, and role mapping functions are not used for EJB and Servlet authorization decisions.

Note:

You cannot use the JACC framework in conjunction with the WebLogic Security framework. The JACC classes used by WebLogic Server do not include an implementation of a Policy object for rendering decisions but instead rely on the java.security.Policy (http://docs.oracle.com/javase/8/docs/api/java/security/Policy.html) object.

WebLogic Server implements a JACC provider that, although fully compliant with JSR-115, is not as optimized as the WebLogic Authentication provider. The Java JACC classes are used for rendering access decisions. Because JSR-115 does not define how to address role mapping, WebLogic JACC classes are used for role-to-principal mapping. For information on developing a JACC provider, see https://javaee.github.io/javaee-spec/javadocs/javax/security/jacc/package-summary.html.

The Authorization Process

Figure 7-1 illustrates how authorization providers (and the associated adjudication and role mapping providers) interact with the WebLogic Security Framework during the authorization process, and an explanation follows.

Figure 7-1 Authorization Providers and the Authorization Process

Description of Figure 7-1 follows
Description of "Figure 7-1 Authorization Providers and the Authorization Process"

Generally, authorization is performed in the following manner:

  1. A user or system process requests a WebLogic resource on which it will attempt to perform a given operation.

  2. The resource container that handles the type of WebLogic resource being requested receives the request (for example, the EJB container receives the request for an EJB resource).

    Note:

    The resource container could be the container that handles any one of the WebLogic Resources described in Security Providers and WebLogic Resources.

  3. The resource container constructs a ContextHandler object that may be used by the configured role mapping providers and the configured authorization providers' Access Decisions to obtain information associated with the context of the request.

    The resource container calls the WebLogic Security Framework, passing in the subject, the WebLogic resource, and optionally, the ContextHandler object (to provide additional input for the decision).

  4. The WebLogic Security Framework calls the configured role mapping providers.

  5. The role mapping providers use the ContextHandler to request various pieces of information about the request. They construct a set of Callback objects that represent the type of information being requested. This set of Callback objects is then passed as an array to the ContextHandler using the handle method.

    The role mapping providers use the values contained in the Callback objects, the subject, and the resource to compute a list of security roles to which the subject making the request is entitled, and pass the list of applicable security roles back to the WebLogic Security Framework.

  6. The WebLogic Security Framework delegates the actual decision about whether the subject is entitled to perform the requested action on the WebLogic resource to the configured authorization providers.

    The authorization providers' Access Decisions also use the ContextHandler to request various pieces of information about the request. They too construct a set of Callback objects that represent the type of information being requested. This set of Callback objects is then passed as an array to the ContextHandler using the handle method. (The process is the same as described for role mapping providers in Step 5.)

  7. The isAccessAllowed method of each configured authorization provider's Access Decision is called to determine if the subject is authorized to perform the requested access, based on the ContextHandler, subject, WebLogic resource, and security roles. Each isAccessAllowed method can return one of three values:

    • PERMIT, indicates that the requested access is permitted.

    • DENY, indicates that the requested access is explicitly denied.

    • ABSTAIN, indicates that the Access Decision was unable to render an explicit decision.

    This process continues until all Access Decisions are used.

  8. The WebLogic Security Framework delegates the job of reconciling any discrepancies among the results rendered by the configured authorization providers' Access Decisions to the adjudication provider. The adjudication provider determines the ultimate outcome of the authorization decision.

  9. The adjudication provider returns either a TRUE or FALSE verdict, which is forwarded to the resource container through the WebLogic Security Framework.

    • If the decision is TRUE, the resource container dispatches the request to the protected WebLogic resource.

    • If the decision is FALSE, the resource container throws a security exception that indicates that the requestor was not authorized to perform the requested access on the protected WebLogic resource.

Do You Need to Develop a Custom Authorization Provider?

The default (that is, active) security realm for WebLogic Server includes the WebLogic Authorization provider and the XACML Authorization provider.

Note:

The WebLogic Authorization provider, also referred to as the DefaultAuthorizer, is deprecated in WebLogic Server 14.1.1.0.0 and will be removed in a future release. Instead, the XACML Authorization provider is the default authorization provider.

The XACML Authorization provider returns an access decision using a policy-based authorization engine to determine if a particular user is allowed access to a protected WebLogic resource. The XACML Authorization provider also supports the deployment and undeployment of security policies within the system. If you want to use an authorization mechanism that already exists within your organization, you could create a custom authorization provider to tie into that system.

Does Your Custom Authorization Provider Need to Support Application Versioning?

All authorization, role mapping, and credential mapping providers for the security realm must support application versioning in order for an application to be deployed using versions. If you develop a custom security provider for authorization, role mapping, or credential mapping and need to support versioned applications, you must implement the Versionable Application SSPI, as described in Versionable Application Providers.

Is Your Custom Authorization Provider Thread Safe?

For the best performance, and by default, Weblogic Server supports parallel modification to security policy and roles during application and module deployment. For this reason, deployable authorization and role mapping providers configured in the security realm should support parallel calls. The WebLogic deployable XACML Authorization and Role Mapping providers meet this requirement.

However, custom deployable authorization and role mapping providers may or may not support parallel calls. If your custom deployable authorization or role mapping providers do not support parallel calls, you need to disable the parallel security policy and role modification and instead enforce a synchronization mechanism that results in each application and module being placed in a queue and deployed sequentially.

Note:

Enabling the synchronization mechanism affects every deployable provider configured in the realm, including the predefined WebLogic Server providers. Enabling the synchronization mechanism may negatively impact the performance of these providers.

See Administering Security for Oracle WebLogic Server for information on how to turn on this synchronization enforcement mechanism.

How to Develop a Custom Authorization Provider

If the XACML Authorization provider does not meet your needs, you can develop a custom authorization provider by following these steps:

  1. Create Runtime Classes Using the Appropriate SSPIs, or, optionally, implement the Bulk Authorization Providers

  2. Optionally, implement the Policy Consumer SSPI

  3. Optionally, implement the PolicyStoreMBean

  4. Generate an MBean type for your custom authorization provider by completing the steps described in Generate an MBean Type Using the WebLogic MBeanMaker.

  5. Configure the Custom Authorization Provider Using the Administration Console

  6. Provide a Mechanism for Security Policy Management

Create Runtime Classes Using the Appropriate SSPIs

Before you start creating runtime classes, you should first:

When you understand this information and have made your design decisions, create the runtime classes for your custom authorization provider by following these steps:

For an example of how to create a runtime class for a custom authorization provider, see Example: Creating the Runtime Class for the Sample Authorization Provider.

Implement the AuthorizationProvider SSPI

To implement the AuthorizationProvider SSPI, provide implementations for the methods described in Understand the Purpose of the Provider SSPIs and the following method:

  • getAccessDecision

    public AccessDecision getAccessDecision();
    

    The getAccessDecision method obtains the implementation of the AccessDecision SSPI. For a single runtime class called MyAuthorizationProviderImpl.java, the implementation of the getAccessDecision method would be:

    return this;
    

    If there are two runtime classes, then the implementation of the getAccessDecision method could be:

    return new MyAccessDecisionImpl;
    

    This is because the runtime class that implements the AuthorizationProvider SSPI is used as a factory to obtain classes that implement the AccessDecision SSPI.

See Java API Reference for Oracle WebLogic Server for the AuthorizationProvider SSPI.

Implement the DeployableAuthorizationProviderV2 SSPI

To implement the DeployableAuthorizationProviderV2 SSPI, provide implementations for the methods described in Understand the Purpose of the Provider SSPIs, Implement the AuthorizationProvider SSPI, and the following methods:

  • deleteApplicationPolicies

    public void deleteApplicationPolicies(ApplicationInfo application) throws ResourceRemovalException
    

    The deleteApplicationPolicies method deletes all policies for an application. The deleteApplicationPolicies method is called only on the Administration Server.

  • deployExcludedPolicy

    public void deleteApplicationPolicies(DeployPolicyHandle handle, Resource
     resource) throws ResourceCreationException
    

    The deployExcludedPolicy method deploys a policy that always denies access. If a policy already exists, it is removed and replaced by this policy.

  • deployPolicy

    public void deployPolicy(DeployPolicyHandle handle, Resource resource,
     String[] roleNames) throws ResourceCreationException
    

    The deployPolicy method creates a security policy on behalf of a deployed Web application or EJB, based on the WebLogic resource to which the security policy should apply and the security role names that are in the security policy.

  • deployUncheckedPolicy

    public void deployUncheckedPolicy(DeployPolicyHandle handle, Resource
     resource) throws ResourceCreationException
    

    The deployUncheckedPolicy method deploys a policy that always grants access. If a policy already exists, it is removed and replaced by this policy.

  • endDeployPolicies

    public void endDeployPolicies(DeployPolicyHandle handle) throws
     ResourceCreationException
    

    The deployExcludedPolicy method deploys a policy that always denies access. If a policy already exists, it is removed and replaced by this policy.

  • startDeployPolicies

    public deployPolicyHandle startDeployPolicies(ApplicationInfo application)
     throws DeployHandleCreationException
    

    The startDeployPolicies method marks the beginning of an application policy deployment and is called on all servers within a WebLogic Server domain where an application is targeted.

  • undeployAllPolicies

    public void undeployAllPolicies(DeployPolicyHandle handle) throws
     ResourceRemovalException
    

    The undeployAllPolicies method deletes a set of policy definitions on behalf of an undeployed Web application or EJB.

See Java API Reference for Oracle WebLogic Server for the DeployableAuthorizationProviderV2 SSPI.

The ApplicationInfo Interface

The ApplicationInfo interface passes data about an application deployment to a security provider. You can use this data to uniquely identity the application.

The Security Framework implements the ApplicationInfo interface for your convenience. You do not need to implement any methods for this interface.

The DeployableAuthorizationProviderV2 and DeployableRoleProviderV2 interfaces use ApplicationInfo. For example, consider an implementation of the DeployableAuthorizationProviderV2 methods. The Security Framework calls the DeployableAuthorizationProviderV2 startDeployPolicies method and passes in the ApplicationInfo interface for this application. The ApplicationInfo data is determined based on the information supplied in the WebLogic Server Administration Console when an application is deployed.

The startDeployPolicies method returns DeployPolicyHandle, which you can then use in the other DeployableAuthorizationProviderV2 methods.

You use the ApplicationInfo interface to get the application identifier, the component name, and the component type for this application. Component type can be APPLICATION, CONTROL_RESOURCE, EJB, or WEBAPP, as defined in the ApplicationInfo.ComponentType class.

The following example shows one way to accomplish this task:

public DeployPolicyHandle startDeployPolicies(ApplicationInfo appInfo)
    throws DeployHandleCreationException
     :
// Obtain the application information...
    String appId = appInfo.getApplicationIdentifier();
    ComponentType compType = appInfo.getComponentType();
    String compName = appInfo.getComponentName();

The Security Framework calls the DeployableAuthorizationProviderV2 deleteApplicationPolicies method and passes in the ApplicationInfo interface for this application. The deleteApplicationPolicies method deletes all policies for an application and is called (only on the Administration Server within a WebLogic Server domain) at the time an application is deleted.

Implement the AccessDecision SSPI

When you implement the AccessDecision SSPI, you must provide implementations for the following methods:

  • isAccessAllowed

    public Result isAccessAllowed(Subject subject, Map roles,
    Resource resource, ContextHandler handler, Direction direction) throws InvalidPrincipalException
    

    The isAccessAllowed method utilizes information contained within the subject to determine if the requestor should be allowed to access a protected method. The isAccessAllowed method may be called prior to or after a request, and returns values of PERMIT, DENY, or ABSTAIN. If multiple Access Decisions are configured and return conflicting values, an adjudication provider will be needed to determine a final result. For more information, see Adjudication Providers.

  • isProtectedResource

    public boolean isProtectedResource(Subject subject, Resource resource) throws InvalidPrincipalException
    

    The isProtectedResource method is used to determine whether the specified WebLogic resource is protected, without incurring the cost of an actual access check. It is only a lightweight mechanism because it does not compute a set of security roles that may be granted to the caller's subject.

See Java API Reference for Oracle WebLogic Server for the AccessDecision SSPI.

Example: Creating the Runtime Class for the Sample Authorization Provider

Example 7-1 shows the SampleAuthorizationProviderImpl.java class, which is the runtime class for the sample authorization provider. This runtime class includes implementations for:

Example 7-1 SimpleSampleAuthorizationProviderImpl.java

package examples.security.providers.authorization.simple;
import java.security.Principal;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.security.auth.Subject;
import weblogic.management.security.ProviderMBean;
import weblogic.security.SubjectUtils;
import weblogic.security.WLSPrincipals;
import weblogic.security.service.ContextHandler;
import weblogic.security.spi.AccessDecision;
import weblogic.security.spi.ApplicationInfo;
import weblogic.security.spi.ApplicationInfo.ComponentType;
import weblogic.security.spi.DeployableAuthorizationProviderV2;
import weblogic.security.spi.DeployPolicyHandle;
import weblogic.security.spi.Direction;
import weblogic.security.spi.InvalidPrincipalException;
import weblogic.security.spi.Resource;
import weblogic.security.spi.Result;
import weblogic.security.spi.SecurityServices;
import weblogic.security.spi.VersionableApplicationProvider;
public final class SimpleSampleAuthorizationProviderImpl implements
DeployableAuthorizationProviderV2, AccessDecision, VersionableApplicationProvider
{
   private static String[] NO_ACCESS = new String[0];
   private static String[] ALL_ACCESS = new String[] {WLSPrincipals.getEveryoneGroupname()};
   private String description;
   private SimpleSampleAuthorizerDatabase database;
   public void initialize(ProviderMBean mbean, SecurityServices services)
   {
      System.out.println("SimpleSampleAuthorizationProviderImpl.initialize");
      SimpleSampleAuthorizerMBean myMBean = (SimpleSampleAuthorizerMBean)mbean;
      description = myMBean.getDescription() + "\n" + myMBean.getVersion();
      database = new SimpleSampleAuthorizerDatabase(myMBean);
   }
   public String getDescription()
   {
      return description;
   }
   public void shutdown()
   {
      System.out.println("SampleAuthorizationProviderImpl.shutdown");
   }
   public AccessDecision getAccessDecision()
   {
      return this;
   }
   public Result isAccessAllowed(Subject subject, Map roles, Resource resource, 
   ContextHandler handler, Direction direction) 
   {
      System.out.println("SimpleSampleAuthorizationProviderImpl.isAccessAllowed");
      System.out.println("\tsubject\t= " + subject);
      System.out.println("\troles\t= " + roles);
      System.out.println("\tresource\t= " + resource);
      System.out.println("\tdirection\t= " + direction);
      Set principals = subject.getPrincipals();
      for (Resource res = resource; res != null; res = res.getParentResource()) {
         if (database.policyExists(res)) {
            Result result = isAccessAllowed(res, subject, roles);
            System.out.println("\tallowed\t= " + result);
            return result;
         }
      }
      Result result = Result.ABSTAIN;
      System.out.println("\tallowed\t= " + result);
      return result;
   }
   public boolean isProtectedResource(Subject subject, Resource resource) throws 
   InvalidPrincipalException 
   {
      System.out.println("SimpleSampleAuthorizationProviderImpl.
        isProtectedResource");
      System.out.println("\tsubject\t= " + subject);
      System.out.println("\tresource\t= " + resource);
      for (Resource res = resource; res != null; res = res.getParentResource()) {
         if (database.policyExists(res)) {
            System.out.println("\tprotected\t= true");
            return true;
         }
      }
      System.out.println("\tprotected\t= false");
      return false;
   }
public DeployPolicyHandle startDeployPolicies(ApplicationInfo application)
{
   String appId = application.getApplicationIdentifier();
   String compName = application.getComponentName();
   ComponentType compType = application.getComponentType();
   DeployPolicyHandle handle = new    SampleDeployPolicyHandle(appId,compName,compType);
   database.removePoliciesForComponent(appId, compName, compType);
   return handle;
  public void deployPolicy(DeployPolicyHandle handle,
Resource resource, String[] roleNamesAllowed)
{
   System.out.println("SimpleSampleAuthorizationProviderImpl.deployPolicy");
   System.out.println("\thandle\t= " + ((SampleDeployPolicyHandle)handle).toString());
   System.out.println("\tresource\t= " + resource);
   for (int i = 0; roleNamesAllowed != null && i < roleNamesAllowed.length; i++) {
     System.out.println("\troleNamesAllowed[" + i + "]\t= " + roleNamesAllowed[i]);
}
database.setPolicy(resource, roleNamesAllowed);
}
   public void deployUncheckedPolicy(DeployPolicyHandle handle, Resource resource)
{
   System.out.println("SimpleSampleAuthorizationProviderImpl.deployUncheckedPolicy");
   System.out.println("\thandle\t= " + ((SampleDeployPolicyHandle)handle).toString());
   System.out.println("\tresource\t= " + resource);
   database.setPolicy(resource, ALL_ACCESS);
}
public void deployExcludedPolicy(DeployPolicyHandle handle, Resource resource)
  {
   System.out.println("SimpleSampleAuthorizationProviderImpl.deployExcludedPolicy");
   System.out.println("\thandle\t= " + ((SampleDeployPolicyHandle)handle).toString());
   System.out.println("\tresource\t= " + resource);
   database.setPolicy(resource, NO_ACCESS);
}
public void endDeployPolicies(DeployPolicyHandle handle)
{
   database.savePolicies();
}
public void undeployAllPolicies(DeployPolicyHandle handle)
{
   System.out.println("SimpleSampleAuthorizationProviderImpl.undeployAllPolicies");
   SampleDeployPolicyHandle myHandle = (SampleDeployPolicyHandle)handle;
   System.out.println("\thandle\t= " + myHandle.toString());

   // remove policies
   database.removePoliciesForComponent(myHandle.getApplication(),
                                       myHandle.getComponent(),
                                       myHandle.getComponentType());
}
public void deleteApplicationPolicies(ApplicationInfo application)
{
   System.out.println("SimpleSampleAuthorizationProviderImpl.deleteApplicationPolicies");
   String appId = application.getApplicationIdentifier();
   System.out.println("\tapplication identifier\t= " + appId);

   // clear out policies for the application
   database.removePoliciesForApplication(appId);
}
private boolean rolesOrSubjectContains(Map roles, Subject subject, String roleOrPrincipalWant)
{
   // first, see if it's a role name match
if (roles.containsKey(roleOrPrincipalWant)) {
     return true;
}

   // second, see if it's a group name match
   if (SubjectUtils.isUserInGroup(subject, roleOrPrincipalWant)) {
     return true;
   }

   // third, see if it's a user name match
   if (roleOrPrincipalWant.equals(SubjectUtils.getUsername(subject))) {
     return true;
   }

   // didn't match
   return false;
}

private Result isAccessAllowed(Resource resource, Subject subject, Map roles)
{
   // loop over the principals and roles in our database who are allowed to access this resource
   for (Enumeration e = database.getPolicy(resource); e.hasMoreElements();) {
     String roleOrPrincipalAllowed = (String)e.nextElement();
     if (rolesOrSubjectContains(roles, subject, roleOrPrincipalAllowed)) {
       return Result.PERMIT;
     }
   }
   // the resource was explicitly mentioned and didn't grant access
   return Result.DENY;
}

public void createApplicationVersion(String appId, String sourceAppId)
{
   System.out.println("SimpleSampleAuthorizationProviderImpl.createApplicationVersion");
   System.out.println("\tapplication identifier\t= " + appId);
   System.out.println("\tsource app identifier\t= " + ((sourceAppId != null) ? sourceAppId : "None"));

   // create new policies when existing application is specified
   if (sourceAppId != null) {
     database.clonePoliciesForApplication(sourceAppId,appId);
   }
}
public void deleteApplicationVersion(String appId)
{
   System.out.println("SimpleSampleAuthorizationProviderImpl.deleteApplicationVersion");
   System.out.println("\tapplication identifier\t= " + appId);

   // clear out policies for the application
   database.removePoliciesForApplication(appId);
}

public void deleteApplication(String appName)
{
   System.out.println("SimpleSampleAuthorizationProviderImpl.deleteApplication");
   System.out.println("\tapplication name\t= " + appName);

   // clear out policies for the application
   database.removePoliciesForApplication(appName);
}

class SampleDeployPolicyHandle implements DeployPolicyHandle
{
   Date date;
   String application;
   String component;
   ComponentType componentType;

   SampleDeployPolicyHandle(String app, String comp, ComponentType type)
{
     this.application = app;
     this.component = comp;
     this.componentType = type;
     this.date = new Date();
}

     public String getApplication() { return application; }
     public String getComponent() { return component; }
     public ComponentType getComponentType() { return componentType; }

     public String toString()
     {
       String name = component;
       if (componentType == ComponentType.APPLICATION)
          name = application;
       return componentType +" "+ name +" ["+ date.toString() +"]";
     }
   }
}

Policy Consumer SSPI

WebLogic Server implements a policy consumer for JMX (MBean) default policies and Web service annotations. This release of WebLogic Server includes an SSPI that authorization providers can use to obtain the policy collections.

The PolicyConsumer SSPI is optional; only those authorization providers that implement the SSPI are called to consume a policy collection.

The SSPI supports both the delivery of initial policy collections and the delivery of updated policy collections.

All authorization providers that support the PolicyConsumer SSPI are called to consume a policy collection. Each authorization provider can choose to skip or obtain the policy collection for a given policy set. In the case where a provider persists policy, the provider need only collect the policy once. However, providers keeping policy in memory can obtain the policy collection again.

The out-of-the-box WebLogic Server Authorization providers persist the policy into LDAP.

Required SSPI Interfaces

If you want your custom authorization provider to support the delivery of policy collections, you must implement three interfaces:

  • weblogic.security.spi.PolicyConsumerFactory

  • weblogic.security.spi.PolicyConsumer

  • weblogic.security.spi.PolicyCollectionHandler

  • These interfaces are described in the sections that follow.

Implement the PolicyConsumerFactory SSPI Interface

An authorization provider implements the PolicyConsumerFactory interface so that an instance of a PolicyConsumer is available to the WebLogic Security Framework. The WebLogic Security Framework calls your PolicyConsumerFactory implementation to obtain the provider's implementation of the policy consumer.

The PolicyConsumerFactory SSPI has one method, which returns your implementation of the PolicyConsumer SSPI interface.

public interface PolicyConsumerFactory
{
/**
* Obtain the implementation of the PolicyConsumer
* security service provider interface (SSPI).
*
* @return a PolicyConsumer SSPI implementation.
*/
public PolicyConsumer getPolicyConsumer();
}
Implement the PolicyConsumer SSPI Interface

The PolicyConsumer SSPI returns a policy collection handler for consumption of a policy collection. It has one method, getPolicyCollectionHandler(), which takes a PolicyCollectionInfo implementation as an argument and returns your implementation of the PolicyCollectionHandler interface.

public interface PolicyConsumer
  {
    /**
     * Obtain a policy handler for consumption of a policy set.
     *
     * @param info the PolicyCollectionInfo for the policy set.
     *
     * @return a PolicyCollectionHandler or NULL which indicates
     *     that the policy set is not needed.
     *
     * @exception ConsumptionException if an error occurs
     *     obtaining the handler and the policy set cannot be consumed.
     */
public PolicyCollectionHandler getPolicyCollectionHandler(
           PolicyCollectionInfo info)
    throws ConsumptionException;
}

The WebLogic Security Framework calls the getPolicyCollectionHandler() method and passes data about a policy collection to a security provider as an implementation of the PolicyCollectionInfo interface. (This interface implementation is provided for you, you do not have to implement it.)

You use the PolicyCollectionInfo getName(), getVersion(), getTimestamp(), and getResourceTypes() methods to discover information about this policy set. You then return a PolicyCollectionHandler, or NULL to indicate that the policy collection is not needed.

public interface PolicyCollectionInfo
{
/**
 * Get the name of the collection.
 */
public String getName();

/**
 * Get the runtime version of the policy.
 */
public String getVersion();

/**
 * Get the timestamp of the policy.
 */
public String getTimestamp();

/**
 * Get the resource types used in the policy collection.
 */
public Resource[] getResouceTypes();
}
Implement the PolicyCollectionHandler SSPI Interface

The PolicyConsumer.getPolicyCollectionHandler() method returns your implementation of the PolicyCollectionHandler interface. PolicyCollectionHandler has three methods: setPolicy, setUncheckedPolicy, and done(). The setPolicy() method takes a resource and role names and sets a policy based on the role. The setUncheckedPolicy() method opens access to everyone.

The done() method signals the completion of the policy collection. We recommend that the done() method remove all old policies for the policy set.

public interface PolicyCollectionHandler
{
     /**
      * Set a policy for the specified resource.
      */
     public void setPolicy(Resource resource, String[] roleNames)
        throws ConsumptionException;

     /**
      * Sets a policy which always grants access.
      */
     public void setUncheckedPolicy(Resource resource)
        throws ConsumptionException;

     /**
      * Signals the completion of the policy collection.
      */
     public void done()
       throws ConsumptionException;

}
Supporting an Updated Policy Collection

To support the delivery of an updated policy collection, all authorization providers that support the PolicyConsumer SSPI need to examine the contents of the PolicyCollectionInfo passed in the PolicyConsumer.getPolicyCollectionHandler() method to determine if a policy set has changed. Each provider must decide (possibly by configuration) how to perform conflict resolution with the initial policy collection and any customized policy received outside of the SSPI.

For the WebLogic Server supplied authorization providers, customized policy will not be replaced by the updated policy collection: all policy from the initial policy collection will be removed and only the customized policies, plus the updated policy collection, will be in effect. If the policy collection info has a different timestamp or version, it's treated as an updated policy collection. The collection name is used as a persistence key.

The PolicyConsumerMBean

Authorization providers that implement the Policy Consumer SSPI must also implement the weblogic.management.security.authorization.PolicyConsumerMBean to indicate that the provider supports policy consumption.

PolicyStoreMBean

This release of WebLogic Server includes support for a new MBean (weblogic.management.security.authorization.PolicyStoreMBean) that allows for standard management (add, delete, get, list, modify, read) of administrator-generated XACML policies and policy sets. An authorization or role mapping provider MBean can optionally implement this MBean interface.

The PolicyStoreMBean methods allow security administrators to manage policy in the server as XACML documents. This includes creating and managing a domain that uses the default XACML provider, as well as managing XACML documents that the administrator has created. The administrator can then use WLST to manage these XACML policies in WebLogic Server.

WebLogic Server includes an implementation of this MBean for use with the out-of-the-box XACML providers, and you can write your own implementation of this MBean for use with your own custom authorization or role mapping providers. The WebLogic Server out-of-the-box XACML providers support the mandatory features of XACML, as described in the XACML 2.0 Core Specification (http://docs.oasis-open.org/xacml/2.0/access_control-xacml-2.0-core-spec-os.pdf), with the Oracle-specific usage described in Securing Resources Using Roles and Policies for Oracle WebLogic Server.

Policies are expressed as XACML 2.0 Policy or PolicySet documents. Custom authorization providers should expect standard Policy or PolicySet documents as described in the XACML 2.0 Core Specification (http://docs.oasis-open.org/xacml/2.0/access_control-xacml-2.0-core-spec-os.pdf). Custom role mapping providers should expect Policy or PolicySet documents consistent with role assignment policies described by the Core and hierarchical role based access control (RBAC) profile of XACML v2.0 (http://docs.oasis-open.org/xacml/2.0/access_control-xacml-2.0-rbac-profile1-spec-os.pdf).

Specifically, the Target must contain:

  • An ActionAttributeDesignator with the id, urn:oasis:names:tc:xacml:1.0:action:action-id, and the value, urn:oasis:names:tc:xacml:2.0:actions:enableRole, according to anyURI-equal. For example:

<Action>
<ActionMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:anyURI-equal">

<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">urn:oasis:names:tc:xacml:2.0
:actions:enableRole
</AttributeValue>

<ActionAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
DataType="http://www.w3.org/2001/XMLSchema#anyURI" MustBePresent="true"/>

</ActionMatch>
</Action>
  • A ResourceAttributeDesignator with the id, urn:oasis:names:tc:xacml:2.0:subject:role, and a value naming the role being assigned, according to string-equal. For example:

<ResourceAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:2.0:resource:resource-ancestor-or-self"
DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
Examining the Format of a XACML Policy File

The XACML 2.0 Core Specification (http://docs.oasis-open.org/xacml/2.0/access_control-xacml-2.0-core-spec-os.pdf) and the Oracle extensions described in Securing Resources Using Roles and Policies for Oracle WebLogic Server are the definitive sources of information for the XACML policy files used by the supplied XACML Authorization and Role Mapping Providers.

However, if as part of your development process you want to take a look at the format of a supported XACML file, perhaps the most convenient way is to use the WebLogic Server Administration Console to export the data from the XACML Authorization or Role Mapping provider's database as a XACML file. Copy this exported XACML file to a file with some other name and use the tool of your choice to review the copy.

Note:

Treat the exported file as read-only. If you do make changes, do not import the file back into WebLogic Server. Editing exported files might result in an unusable WebLogic Server configuration and is not supported.

Using WLST to Add a Policy to the PolicyStoreMBean

Example 7-2 shows an example of using WLST to add a single policy to an instance of the PolicyStoreMBean from a XACML file.

The example assumes that you have defined the properties used in this script elsewhere, in a manner similar to the following lines from an ant script:

<property name="xacml-docs-dir" value="${xacmldir}/xacml-docs"/>
<sysproperty key="file" value="${xacml-docs-dir}/policy-getSubject.xacml"/>

You should avoid entering clear-text passwords in WLST commands in general, and you should especially avoid saving on disk WLST scripts that include clear-text passwords. In these instances you should use a mechanism for passing encrypted passwords instead. See Security for WLST in Understanding the WebLogic Scripting Tool.

Example 7-2 Using WLST to Add a Policy to the PolicyStoreMBean

:
try:
      protocol = System.getProperty("protocol")
      host = System.getProperty("host")
      user = System.getProperty("authuser")
      passwd = System.getProperty("authpwd")
      port = System.getProperty("port")
      dom = System.getProperty("domain")
      rlm = System.getProperty("realm")
      fil = System.getProperty("file")
      prov = System.getProperty("provider")
      stat = System.getProperty("status")

def configure():
try:
      url = protocol + "://" + host + ":" + port
      connect(user,passwd, url)
      path = "/SecurityConfiguration/" + dom + "/Realms/" + rlm + "/" + prov
      print("cd'ing to " + path)
      cd(path)
      print("calling open()")
      xacmlFile = open(fil,"r")
      print("calling read()")
      xacmlDoc = xacmlFile.read()
      print("calling cmo.addPolicy")
      if stat == "none":
          cmo.addPolicy(xacmlDoc)
      else:
          cmo.addPolicy(xacmlDoc, stat)
      print("Add error handling")
:
:

As described in the Navigating and Interrogating MBeans section of Understanding the WebLogic Scripting Tool, when WLST first connects to an instance of WebLogic Server, the variable, cmo (Current Management Object), is initialized to the root of all configuration management objects, DomainMBean. When you navigate to an MBean type, in this case SecurityConfigurationMBean, the value of cmo reflects SecurityConfigurationMBean. When you navigate to an MBean instance, in this case to an Authorizer MBean that implements the PolicyStoreMBean, identified in the example by the variable prov, WLST changes the value of cmo to be the current MBean instance.

The example uses the addPolicy() method of the PolicyStoreMBean to add a policy read from a XACML file to the policy store. Two variants of the addPolicy() method (without and with status) are shown.

If you use an addPolicy() method that does not specify status, it defaults to ACTIVE, which indicates that the policy is evaluated for any decision to which its target applies. You can explicitly set status to be ACTIVE, INACTIVE, or BYREFERENCE. The INACTIVE status indicates that the policy will never be evaluated and is only being stored. The BYREFERENCE status indicates that the policy will only be evaluated when referenced by a policy set that is being evaluated.

You can invoke this type of WLST script from the command line, in a manner similar to the following:

java -Dhost="localhost " -Dprotocol="t3" -Dauthuser="weblogic"
-Dauthpwd="weblogic" -Dport="7001" -Ddomain="mydomain" -Drealm="myrealm"
-Dprovider="Authorizers/XACMLAuthorizer"
-Dfile="C:/XACML/xacml-docs/policy12.xml" -Dstatus="none" weblogic.WLST
XACML/scripts/XACMLaddPolicy.py
Using WLST to Read a PolicySet as a String

Example 7-3 shows an example of using WLST to read a PolicySet as a string.

The example assumes that you have defined the properties used in this script elsewhere, in a manner similar to the following lines from an ant script:

<sysproperty key="identifier"
value="urn:sample:xacml:2.0:wlssecqa:resource:type@E@Fejb@G@M@Oapplication@ENoD
DRolesOrPoliciesEar@M@Omodule@Eejb11inEarMiniAppBean.jar@M@Oejb@EMiniAppBean@
M@Omethod@EgetSubject@M@OmethodInterface@ERemote"/>
<sysproperty key="version" value="1.0"/>

You should avoid entering clear-text passwords in WLST commands in general, and you should especially avoid saving on disk WLST scripts that include clear-text passwords. In these instances you should use a mechanism for passing encrypted passwords instead. See Security for WLST in Understanding the WebLogic Scripting Tool.

Example 7-3 Using WLST to Read a PolicySet as a String

:
:
try:
      print("start XACMLreadPolicySet.py")
      protocol = System.getProperty("protocol")
      host = System.getProperty("host")
      user = System.getProperty("authuser")
      passwd = System.getProperty("authpwd")
      port = System.getProperty("port")
      dom = System.getProperty("domain")
      rlm = System.getProperty("realm")
      prov = System.getProperty("provider")
      id = System.getProperty("identifier")
      vers = System.getProperty("version")
:
:
def configure():
try:
      url = protocol + "://" + host + ":" + port
      connect(user,passwd, url)
      path = "/SecurityConfiguration/" + dom + "/Realms/" + rlm + "/" + prov
      print("cd'ing to " + path)
      cd(path)
      polset = cmo.readPolicySetAsString(id, vers)
      print("readPolicySetAsString() returned the following policy set: " + polset)
      print"Add error handling."
:
:

As described in the XACML 2.0 Core Specification (http://docs.oasis-open.org/xacml/2.0/access_control-xacml-2.0-core-spec-os.pdf), the <PolicySet> element contains a set of <Policy> or other <PolicySet> elements and a specified procedure for combining the results of their evaluation. See the XACML 2.0 Core Specification for complete information.

Bulk Authorization Providers

This release of WebLogic Server includes bulk access versions of the following authorization provider SSPI interfaces:

  • BulkAuthorizationProvider

  • BulkAccessDecision

The bulk access SSPI interfaces allow authorization providers to receive multiple decision requests in one call rather than through multiple calls, typically in a 'for' loop. The intent of the bulk SSPI variants is to allow provider implementations to take advantage of internal performance optimizations, such as detecting that many of the passed-in Resource objects are protected by the same policy and will generate the same decision result.

There are subtle differences in how the non-bulk and bulk versions of the SSPI interfaces are used.

Note that the BulkAccessDecision.isAccessAllowed() method takes a Map of roles, indexed first by Resource object and then by role name (Map<Resource, Map<String, SecurityRole>> roles), that are associated with the subject and should be taken into consideration when making the authorization decision.

The BulkAccessDecision.isAccessAllowed() method returns a Map (indexed by Resource, result) that indicates whether the authorization policies defined for the resources allow the requested methods to be performed.

Configure the Custom Authorization Provider Using the Administration Console

Configuring a custom authorization provider means that you are adding the custom authorization provider to your security realm, where it can be accessed by applications requiring authorization services.

Configuring custom security providers is an administrative task, but it is a task that may also be performed by developers of custom security providers. This section contains information that is important for the person configuring your custom authorization providers:

Managing Authorization Providers and Deployment Descriptors

Some application components, such as Enterprise JavaBeans (EJBs) and Web applications, store relevant deployment information in Java EE and WebLogic Server deployment descriptors. For Web applications, the deployment descriptor files (called web.xml and weblogic.xml) contain information for implementing the Java EE security model, including declarations of security policies. Typically, you will want to include this information when first configuring your authorization providers in the WebLogic Server Administration Console.

Because the Java EE platform standardizes Web application and EJB security in deployment descriptors, WebLogic Server integrates this standard mechanism with its Security Service to give you a choice of techniques for securing Web application and EJB resources. You can use deployment descriptors exclusively, the WebLogic Server Administration Console exclusively, or you can combine the techniques for certain situations.

Depending on the technique you choose, you also need to apply a Security Model. WebLogic supports different security models for individual deployments, and a security model for realm-wide configurations that incorporate the technique you want to use.

When configured to use deployment descriptors, WebLogic Server reads security policy information from the web.xml and weblogic.xml deployment descriptor files (examples of web.xml and weblogic.xml files are shown in Example 7-4 and Example 7-5). This information is then copied into the security provider database for the authorization provider.

Example 7-4 Sample web.xml File

<web-app> 
   <welcome-file-list> 
      <welcome-file>welcome.jsp</welcome-file> 
   </welcome-file-list> 
   <security-constraint> 
      <web-resource-collection>
         <web-resource-name>Success</web-resource-name>
         <url-pattern>/welcome.jsp</url-pattern>
         <http-method>GET</http-method> 
         <http-method>POST</http-method> 
      </web-resource-collection> 
      <auth-constraint> 
         <role-name>developers</role-name> 
      </auth-constraint> 
   </security-constraint> 
   <login-config> 
       <auth-method>BASIC</auth-method> 
       <realm-name>default</realm-name> 
   </login-config> 
   <security-role> 
      <role-name>developers</role-name> 
   </security-role> 
</web-app>

Example 7-5 Sample weblogic.xml File

<weblogic-web-app> 
   <security-role-assignment> 
      <role-name>developers</role-name>
      <principal-name>myGroup</principal-name> 
   </security-role-assignment> 
</weblogic-web-app>
Enabling Security Policy Deployment

If you implemented the DeployableAuthorizationProviderV2 SSPI as part of developing your custom authorization provider and want to support deployable security policies, the person configuring the custom authorization provider (that is, you or an administrator) must be sure that the Policy Deployment Enabled check box in the WebLogic Server Administration Console is checked. Otherwise, deployment for the authorization provider is considered turned off. Therefore, if multiple authorization providers are configured, the Policy Deployment Enabled check box can be used to control which authorization provider is used for security policy deployment.

Provide a Mechanism for Security Policy Management

While configuring a custom authorization provider via the WebLogic Server Administration Console makes it accessible by applications requiring authorization services, you also need to supply administrators with a way to manage this security provider's associated security policies. The WebLogic Authorization provider, for example, supplies administrators with a Policy Editor page that allows them to add, modify, or remove security policies for various WebLogic resources.

Neither the Policy Editor page nor access to it is available to administrators when you develop a custom authorization provider. Therefore, you must provide your own mechanism for security policy management. This mechanism must read and write security policy data (that is, expressions) to and from the custom authorization provider's database.

You can accomplish this task in one of two ways:

Option 1: Develop a Stand-Alone Tool for Security Policy Management

You would typically select this option if you want to develop a tool that is entirely separate from the WebLogic Server Administration Console.

For this option, you do not need to write any console extensions for your custom authorization provider, nor do you need to develop any management MBeans. However, your tool needs to:

  1. Determine the WebLogic resource's ID, since it is not automatically provided to you by the console extension. See WebLogic Resource Identifiers.

  2. Determine how to represent the expressions that make up a security policy. (This representation is entirely up to you and need not be a string.)

  3. Read and write the expressions from and to the custom authorization provider's database.

Option 2: Integrate an Existing Security Policy Management Tool into the Administration Console

You would typically select this option if you have a tool that is separate from the WebLogic Server Administration Console, but you want to launch that tool from the WebLogic Server Administration Console.

For this option, your tool needs to:

  1. Determine the WebLogic resource's ID, since it is not automatically provided to you by the console extension. See WebLogic Resource Identifiers.

  2. Determine how to represent the expressions that make up a security policy. (This representation is entirely up to you and need not be a string.)

  3. Read and write the expressions from and to the custom authorization provider's database.

  4. Link into the WebLogic Server Administration Console using basic console extension techniques.