Skip to content

Latest commit

 

History

History
187 lines (137 loc) · 9.7 KB

2_provider-configuration.adoc

File metadata and controls

187 lines (137 loc) · 9.7 KB

Provider Configuration Subcontract

The Provider Configuration Subcontract defines the requirements placed on providers and implementations such that Policy providers may be integrated with implementations.

Policy Implementation Class

The contract defined by this specification has been designed to work in Jakarta EE 11 or later Jakarta EE environments with the default jakarta.security.jacc.Policy implementation class.

An application server that supports this contract must allow replacement of the top level jakarta.security.jacc.Policy object used by the application server for all applications running on it, in addition to supporting a jakarta.security.jacc.Policy object for individual applications.

Permission Implementation Classes

This contract defines the package, jakarta.security.jacc, that contains (among other things) Permission classes to be used by containers in their access decisions.

Policy Configuration Interface

A Policy Configuration implementation is the object that holds the Permission instances a Policy can use to make its authorization decisions. The Policy Configuration implementation can be replaced if needed, although for most common uses this should not be needed.

Replacement is done via the jakarta.security.jacc.PolicyConfigurationFactory abstract factory class. A default static method, getPolicyConfigurationFactory is provided that uses the system property jakarta.security.jacc.PolicyConfigurationFactory.provider to locate a concrete implementation. The container can alternatively set a custom PolicyConfigurationFactory using the setPolicyConfigurationFactory method. In that case the PolicyConfigurationFactory implementation can come from a container specific configuration, or in case of the Servlet Container from the context property jakarta.security.jacc.PolicyConfigurationFactory.provider. If the PolicyConfigurationFactory has a public constructor with one argument of type PolicyConfigurationFactory, then the container should call this constructor with as argument the PolicyConfigurationFactory instance that is being replaced. This allows a replacement PolicyConfigurationFactory to wrap the existing one and selectively provide extra functionality.

From this factory class a concrete implementation of the Policy Configuration of type jakarta.security.jacc.PolicyConfiguration can be obtained using the method getPolicyConfiguration.

Use of the PolicyConfiguration interface is defined in [a232].

PolicyContext Class and Context Handlers

This jakarta.security.jacc package defines a utility class that is used by containers to communicate policy context identifiers to Policy providers. The utility class is jakarta.security.jacc.PolicyContext, and this class implements static methods that are used to communicate policy relevant context values from containers to Policy providers.

Containers use the static method PolicyContext.setContextID to associate a policy context identifier with a thread on which they are about to call a decision interface of a Policy provider. Policy providers use the static method PolicyContext.getContextID to obtain the context identifier established by a calling container.

The role of policy context identifiers in access decisions is described in [a253].

In addition to the methods used to communicate policy context identifiers, the jakarta.security.jacc.PolicyContext class also provides static methods that allow container specific context handlers that implement the jakarta.security.jacc.PolicyContextHandler interface to be registered with the PolicyContext class.

The PolicyContext class also provides static methods that allow Policy providers to activate registered handlers to obtain additional policy relevant context to apply in their access decisions.

Use of the PolicyContext class is defined in [a232].

PrincipalMapper Interface

A jakarta.security.jacc.PrincipalMapper is an object that maps from a collection of generic Principals or a Subject to well known entities in Jakarta EE. A Subject is a "bag of principles", which can contain any number of principals, with each principal in that bag representing some attribute of the subject in question. A portable Policy does not know which principal represents what entity, as historically no interfaces or annotations have been standardised to mark them as such.

Using the PrincipalMapper a given number of well known entities can be retrieved from the Subject.

The following well known entities are supported:

  • The caller principal - a java.security.Principal containing the name of the current authenticated user (if any).

  • The role - a java.lang.String representing the logical application role associated with the caller principal.

A PrincipalMapper is intended to be used by a Policy, but should work outside a Policy (for instance, during request processing in a Servlet container).

What a Provider Must Do

A Jakarta Authorization implementation can be provided with custom classes that implement the PolicyConfigurationFactory class and PolicyConfiguration interface. These classes can be used by the Policy implementation class installed for use by the Jakarta Authorization implementation. In the case where the provider is not seeking to replace the Policy implementation used by the Jakarta Authorization implementation, no other components need be provided.

If the provider is seeking to replace the Policy implementation used by the Jakarta Authorization implementation, then the Jakarta Authorization implementation must be provided with an environment specific Policy implementation class.

A replacement Policy object must assume responsibility for performing all policy decisions within the entire application server (in case the Jakarta Authorization implementation is integrated into an application server) in which it is installed that are requested by way of the Policy interface that it implements. Alternatively or additionally a replacement Policy can be installed for an individual (web) application.

A replacement Policy object may accomplish this by delegating jakarta.security.jacc policy decisions to the corresponding default Policy implementation class. A replacement Policy object that fully or partially relies in this way on the corresponding default Policy implementation class must identify itself in its installation instructions as a “delegating Policy provider”.

What the Jakarta Authorization Implementation Must Do

A Jakarta Authorization implementation must bundle or install the Jakarta Authorization API. This API consists of all types from the jakarta.security.jacc package. It must provide default implementations of its interfaces and abstract classes.

To enable delegation of jakarta.security.jacc policy decisions to default Policy providers, all Jakarta Authorization implementations must support the following Policy replacement algorithm. The intent of the algorithm is to ensure that Policy objects can capture the instance of the corresponding default Policy object during their integration into a container and such that they may delegate policy evaluations to it.

For each Jakarta EE 11 or later version Jakarta EE compatible implementation, if the system property "`jakarta.security.jacc.policy.provider`” is defined, the Jakarta Authorization implementation must construct an instance of the class identified by the system property, confirm that the resulting object is an instance of jakarta.security.jacc.Policy, and set, by calling the jakarta.security.jacc.PolicyFactory#setPolicy method, the resulting object as the corresponding Policy object used by the Jakarta Authorization implementation.

For example:

String policyClassName = System.getProperty("jakarta.security.jacc.policy.provider");

if (policyClassName != null) {
    try {
         Policy policy = loadPolicy(policyClassName);
         PolicyFactory.getPolicyFactory().setPolicy(policy);
     } catch (Exception e) {
         // ...
     }
}

private Policy loadPolicy(String policyClassName) throws ReflectiveOperationException, SecurityException {
        Object policyInstance =
                Thread.currentThread()
                      .getContextClassLoader()
                      .loadClass(policyClassName)
                      .getDeclaredConstructor()
                      .newInstance();

        if (!(policyInstance instanceof Policy)) {
            throw new RuntimeException("..."));
        }

        return (Policy) policyInstance;
    }

Even when a Jakarta Authorization implementation has used the system property defined in this section to replace a Policy object used by the Jakarta Authorization implementation, the Jakarta Authorization implementation MUST be prepared for an individual web application to replace the Policy object once again.

For example:

@WebListener
public class PolicyRegistrationListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        PolicyFactory policyFactory = PolicyFactory.getPolicyFactory();
        policyFactory.setPolicy(new TestPolicy(policyFactory.getPolicy()));
    }
}

The Jakarta Authorization implementation MAY forbid setting the Policy by an application after that application has been taken into service (starting to process requests).

The requirements of this section have been designed to ensure that Jakarta Authorization implementations support Policy replacement and to facilitate delegation to a default Policy provider. These requirements should not be interpreted as placing any restrictions on the delegation patterns that may be implemented by replacement Policy modules.