The oak-authorization-cug module provides a alternative authorization model intended to limit read access to certain paths for a selected, small set of Principals.
These restricted areas called CUG are marked by a dedicated policy type and effectively prevent read-access for anybody not explicitly allowed.
This implies that the CUG-authorization model solely evaluates and enforces read access to regular nodes and properties. Therefore it may only be used as an additional, complementary authorization scheme while the primary module(s) is/are in charge of enforcing the complete set of permissions including read/write access, repository operations and any kind of special permissions like reading and writing access control content. See section Combining Multiple Authorization Models for information aggregating access control management and permission evaluation from different implementations.
By default the oak-authorization-cug model is disabled and it requires manual configuration steps in order to plug it into the Oak security setup.
Once deployed this authorization configuration can be used in the following two operation modes:
The Jackrabbit API defines an extension of the JCR AccessControlPolicy interface intended to grant the ability to perform certain actions to a set of Principals:
See Jackrabbit API for details and the methods exposed by the interface.
The module comes with the following extension in the org.apache.jackrabbit.oak.spi.security.authorization.cug package space:
The CugPolicy interface extends the PrincipalSetPolicy and JackrabbitAccessControlPolicy interfaces provided by Jackrabbit API. It comes with the following set of methods that allow to read and modify the set of Principals that will be allowed to access the restricted area defined by a given policy instance.
CugPolicy extends PrincipalSetPolicy, JackrabbitAccessControlPolicy Set<Principal> getPrincipals(); boolean addPrincipals(@Nonnull Principal... principals) throws AccessControlException; boolean removePrincipals(@Nonnull Principal... principals) throws AccessControlException;
The CugExclude allows to customize the set of principals excluded from evaluation of the restricted areas. These principals will consequently never be prevented from accessing any of the configured CUGs and read permission evaluation is delegated to any other module present in the setup.
The feature ships with two implementations out of the box:
See also section Pluggability below.
The access control management part of the CUG authorization models follows the requirements defined by JSR 283 the extensions defined by Jackrabbit API (see section Access Control Management with the following characterstics:
This implemenation of the JackrabbitAccessControlManager only supports a subset of privileges, namely jcr:read, rep:readProperties, rep:readNodes.
Only a single type of access control policies (CugPolicy) is exposed and accepted by the access control manager. Once effective each CUG policy creates a restricted area starting at the target node and inherited to the complete subtree defined therein.
Depending on the value of the mandatory PARAM_CUG_SUPPORTED_PATHS configuration option creation (and evaluation) of CUG policies can be limited to certain paths within the repository. Within these supported paths CUGs can be nested. Note however, that the principal set defined with a given CugPolicy is not inherited to the nested policies applied in the subtree.
Note: For performance reasons it is recommended to limited the usage of CugPolicys to a single or a couple of subtrees in the repository.
As stated above evaluation of the restricted areas requires the PARAM_CUG_ENABLED configuration option to be set to true. This switch allows to setup restricted areas in a staging enviroment and only let them take effect in the public facing production instance.
If permission evaluation is enabled, the PermissionProvider implementation associated with the authorization model will prevent read access to all restricted areas defined by a CugPolicy. Only Principals explicitly allowed by the policy itself or the globally configured CugExclude will be granted read permissions to the affected items in the subtree.
For example, applying and persisting a new CugPolicy at path _/content/restricted/apachefoundation, setting the principal names to apache-members and jackrabbit-pmc will prevent read access to the tree defined by this path for all Subjects that doesn’t match any of the two criteria:
This further implies that the PermissionProvider will only evaluate regular read permissions (i.e. READ_NODE and READ_PROPERTY). Evaluation of any other permissions including reading the cug policy node (access control content) is consequently delegated to other authorization modules. In case there was no module dealing with these permissions, access will be denied (see in section Combining Multiple Authorization Models for details).
CUG policies defined by this module in a dedicate node name rep:cugPolicy of type rep:CugPolicy. This node is defined by a dedicate mixin type rep:CugMixin (similar to rep:AccessControllable) and has a single mandatory, protected property which stores the name of principals that are granted read access in the restricted area:
[rep:CugMixin] mixin + rep:cugPolicy (rep:CugPolicy) protected IGNORE [rep:CugPolicy] > rep:Policy - rep:principalNames (STRING) multiple protected mandatory IGNORE
Note: the multivalued rep:principalNames property reflects the fact that CUGs are intended to be used for small principal sets, preferably java.security.acl.Group principals.
The consistency of this content structure both on creation and modification is asserted by a dedicated CugValidatorProvider. The corresponding error are all of type AccessControl with the following codes:
Code | Message |
---|---|
0020 | Attempt to change primary type of/to cug policy |
0021 | Wrong primary type of ‘rep:cugPolicy’ node |
0022 | Access controlled not not of mixin ‘rep:CugMixin’ |
0023 | Wrong name of node with primary type ‘rep:CugPolicy’ |
The CUG authorization extension is an optional feature that requires mandatory configuration: this includes defining the supported paths and enabling the permission evaluation.
The org.apache.jackrabbit.oak.spi.security.authorization.cug.impl.CugConfiguration supports the following configuration parameters:
Parameter | Type | Default | Description |
---|---|---|---|
PARAM_CUG_ENABLED | boolean | false | Flag to enable evaluation of CUG policies upon read-access. |
PARAM_CUG_SUPPORTED_PATHS | Set<String> | - | Paths under which CUGs can be created and will be evaluated. |
PARAM_RANKING | int | 200 | Ranking within the composite authorization setup. |
Note: depending on other the authorization models deployed in the composite setup, the number of CUGs used in a given deployment as well as other factors such as predominant read vs. read-write, the performance of overall permission evaluation may benefit from changing the default ranking of the CUG authorization model.
The CUG authorization setup can be further customized by configuring the CugExcludeImpl service with allows to list additional principals that need to be excluded from the evaluation of restricted areas:
Parameter | Type | Default | Description |
---|---|---|---|
principalNames | Set<String> | - | Name of principals that are always excluded from CUG evaluation. |
Note: this is an optional feature to extend the default exclusion list. Alternatively, it is possible to plug a custom CugExclude implementation matching specific needs (see below).
The following section describes how to deploy the CUG authorization model into an Oak repository and how to customize the CugExclude extension point.
Note: the reverse steps can be used to completely disable the CUG authorization model in case it is not needed for a given repository installation but shipped by a vendor such as e.g. Adobe AEM 6.3.
The following steps are required in order to deploy the CUG authorization model in an OSGi-base Oak repository:
The third step will enforce the recreation of the SecurityProvider and hence trigger the RepositoryInitializer provided by the CUG authorization module.
The following example shows a simplified setup that contains the CugConfiguration as additional authorization model (second position in the aggregation). See also unit tests for an alternative approach.
// setup CugConfiguration ConfigurationParameters params = ConfigurationParameters.of(AuthorizationConfiguration.NAME, ConfigurationParameters.of(ConfigurationParameters.of( CugConstants.PARAM_CUG_SUPPORTED_PATHS, "/content", CugConstants.PARAM_CUG_ENABLED, true))); CugConfiguration cug = new CugConfiguration(); cug.setParameters(params); // bind it to the security provider (simplified => subclassing required due to protected access) SecurityProviderImpl securityProvider = new SecurityProviderImpl(); securityProvider.bindAuthorizationConfiguration(cug); // create the Oak repository (alternatively: create the JCR repository) Oak oak = new Oak() .with(new InitialContent()) // TODO: add all required editors .with(securityProvider); withEditors(oak); ContentRepository contentRepository = oak.createContentRepository();
The following steps are required in order to customize the CugExclude implementation in a OSGi-based repository setup. Ultimately the implementation needs to be referenced in the org.apache.jackrabbit.oak.spi.security.authorization.cug.impl.CugConfiguration.
@Component() @Service(CugExclude.class) public class MyCugExclude implements CugExclude { private static final Principal PRINCIPAL_APACHE_MEMBERS = new PrincipalImpl("apache-members"); private static final Principal PRINCIPAL_JACKRABBIT_PMC = new PrincipalImpl("jackrabbit_pmc"); public MyCugExclude() {} //-----------------------------------------------------< CugExclude >--- @Override public boolean isExcluded(@Nonnull Set<Principal> principals) { return principals.contains(PRINCIPAL_APACHE_MEMBERS) || principals.contains(PRINCIPAL_JACKRABBIT_PMC); } //------------------------------------------------< SCR Integration >--- @Activate private void activate(Map<String, Object> properties) { } }