Security

Draft comment:
This topic is shared by ICS, Filenet 5.5.10. As of: 2023-05-10

Authentication and JAAS

Authentication is the act of verifying a user's identity based on credentials they present. Authentication in the Content Engine functions differently, depending on how a request arrives at the server. The Content Engine server accepts incoming requests over two transport protocols: Enterprise Java™ (EJB) and Content Engine Web Service (CEWS) transports.

The Content Engine resides within a Java Platform, Enterprise Edition (Java EE) application server, and uses the Java Authentication and Authorization (JAAS) standard as the basis for authentication. The JAAS programming model is a standard Java framework that manages authentication and authorization. FileNet P8 Platform uses JAAS to perform authentication, but not authorization. (Authorization is performed by FileNet P8 Platform code.) Authentication occurs between a Java EE client application and Java EE application server, and one or more JAAS LoginModules.

Authentication over the EJB transport is handled by using the JAAS framework. FileNet code is not involved in this authentication process. Callers are authenticated by the Java EE application server before they can access the EJB layer. A JAAS Subject is created that contains the credentials of the authenticated user, and the Subject is returned to the client application.

Authentication over the CEWS transport is handled differently and FileNet code is involved in the authentication process of a web service-based client. The WS-Security standard defines how security credentials are formatted and inserted in a web service request. When a web service request arrives in the Content Engine server, the CEWS listener extracts the WS-Security header and based on its contents, performs a JAAS login. If this JAAS login is successful, the CEWS listener passes the request to the Content Engine EJB layer within the EJB container.

The Content Engine supports the WS-Security Username/Password Token profile, and the Kerberos profile. However, to be able to use binary security tokens as defined in the WS-Security standard, FileNet P8 Platform provides a pluggable authentication mechanism: the Content Engine Web Service Extensible Authentication Framework (WS-EAF). WS-EAF consists of a set of conventions for writing a custom JAAS LoginModule that is able to interact with the FileNet P8 CEWS listener to obtain the credentials that are present in a WS-Security header of an incoming request packet. For more information, see the WS-EAF Developer's Guide. This document contains details and code samples for extending the framework.

LoginModules

Authentication occurs in JAAS LoginModules, which are specified in a JAAS configuration file. The use of JAAS configuration files allows authentication to be dynamically configured for both clients and servers in a Java Platform, Enterprise Edition environment.

Generally, a Java client program that accesses the Content Engine uses the installed JAAS configuration file for the relevant application server (such as jaas.conf.WebSphere or jaas.conf.WebLogic). A client can also choose to use jaas.conf.WSI. In this case, the definition of the FileNet P8 stanza in the configuration file uses the CEWS transport, rather than the default EJB transport.

The configuration file contains one JAAS configuration (stanza), and within each JAAS configuration (stanza) is a list of LoginModules. Each entry in the list specifies the fully qualified name of a Java LoginModule class, a flag (set to Required, Optional, Sufficient, or Requisite), and options for that LoginModule. The following stanzas are supplied:

  • FileNetP8

    This configuration is used by all stand-alone (thick) Java clients. For compatibility, this stanza can also be used by servlet-based Java clients, although the FileNetP8Server stanza is now supplied for this purpose. When the jaas.conf.WSI file is used, this stanza specifies the CEWS transport, rather than the EJB transport (specified in this stanza for the jaas.conf.<app server> files).

  • FileNetP8Engine

    (Not for client use.) This configuration is used internally by the CEWS transport handling processes, and must not be used by clients. You can only modify this stanza only if you are using WS-EAF.

  • FileNetP8Server

    This configuration is used by servlet-based clients that run within an application server container.

  • FileNetP8WSI

    This configuration can be used by Java clients (stand-alone or within a servlet) that need to use the CEWS transport, rather than the default EJB transport. Another way to accomplish this is to use the jaas.conf.WSI sample configuration file with the FileNetP8 configuration.

  • FileNetP8KerberosService

    (Not for client use.) This configuration is used internally by the CEWS transport handling processes, and must not be used by clients.

There are a number of other stanzas (such as Credentials, ReceivedCredentials, HttpCredentials) that are required by the server while it handles the CEWS transport. These stanzas can be removed safely from a JAAS configuration file that is used by a client.

When a client application attempts to authenticate, the JAAS framework dynamically determines the set of LoginModules to invoke based on the contents of the configuration file. Authentication succeeds only if all LoginModules marked either Required or Requisite succeed. If no Required or Requisite LoginModules succeed, then at least one Sufficient or Optional LoginModule must succeed.

A set of sample JAAS configuration files are supplied for you to use to set up your own configurations. The FileNet P8 installation program stores these sample files in the \config\samples subdirectory of your Content Engine installation directory. By default, the installation directory for the Windows version of Content Engine is C:\Program Files\IBM\FileNet\ContentEngine, and for the non-Windows version is /opt/IBM/FileNet/ContentEngine. Each application server has slightly different requirements, and the files are named for the supported application server environments: jaas.conf.WebLogic, jaas.conf.jaas.conf.WebSphere, and a special CEWS transport configuration file, jaas.conf.WSI.

Authorization

Authorization to access objects within an object store is verified after authentication occurs. Every object has its own security settings. Where multiple versions of a document exist, each version has its own security settings.

Assets that are managed in the Content Engine and Process Engine are protected and can be seen or modified according to a user's access rights only. Each object has its own security, which controls a user's or group's access to that object. An object can have several rules that govern access to it. For example, users in GroupA might have permission only to view the object, while UserB has permission to view and modify the object. Each rule (also called access control) is represented by a Permission object, which establishes the access that is granted to a user or group (the grantee), and contains a reference to the user or group that is assigned the permission. For more information about users and groups, see Grantees, and to the reference help provided for the User, Group, SecurityPrincipal, and Permission interfaces.

The access level specifies the access rights, such as read and write permission, held by or denied to the referenced grantee, and determines the activities that the grantee can perform on objects. A system administrator is typically responsible for establishing the type of access that is granted to users and groups.

Tip: In the security model, deny takes precedence over allow, which can lead to counterintuitive expectations. For example, if you deny write access to a group and then allow write access to a specific member of that group, that member's write access is still denied.

A Permissions collection represents the full set of access control entries (ACEs) associated with an object and forms the object's Access Control List (ACL). To grant rights, call methods on the AccessPermission object to set the appropriate property, add the permission to the object's permissions list, and then save the modified AccessPermissionList collection on the object. Removing access rights is a similar process. For a code sample that illustrates how to set access rights, see Working with Security.

Access to an object can also be affected by properties that are set at the Content Engine level. Notably, the settings of the ModificationAccessRequired and TargetAccessRequired properties can further restrict a user's access to, and ability to modify, an object's custom properties and its object valued properties. You cannot set or retrieve the values of the ModificationAccessRequired and TargetAccessRequired properties by using the Content Engine APIs. However, depending on the requirements of your application, you might need to understand the effect that these properties can have on object access. For more information, see Property modification access and Target access required.

Within each ACE is a security identifier (SID). The SID is a globally unique value that identifies a security principal (a user or group to which Content Engine grants or denies object access).

IBM® FileNet P8 uses the LDAP directory server's built-in attributes as stable and unique user or group identifiers. The unique ID is converted to a SID format to be stored in the object's ACL. After a user or group is created in the LDAP server and the SID attribute value is populated, the value must not be changed. For more information about the SID and to see the list of default SID attributes for LDAP servers that are supported by Content Engine, see Security identifier (SID) in the What are access rights? topic

Because most of the default SID attributes are generated by the LDAP server itself during user or group creation and are machine-dependent, complications can arise during backup, restore, moves, and duplication of the underlying LDAP server and hardware. To introduce configuration flexibility and to avoid problems that are associated with a fixed SID attribute, you are not restricted to the default attributes provided by the LDAP server when you configure the SID. Instead, you can choose other LDAP attributes, such as Distinguished Name (DN), employee number, and so on, to function as the SID.

The value of the attribute that you choose for your user and group IDs must be unique across the configured LDAP realms. Because the Content Engine authorization process uses the attribute as the single identifier of a user or group in an LDAP repository, a non-unique value causes authorization failures. You specify the attribute through the value of the UserUniqueIDAttribute and GroupUniqueIDAttribute properties of the DirectoryConfiguration class. The values are typically the same for both properties, but it is possible to specify different values for each property if required by your design.

Currently, you are limited to using as SID attributes only those LDAP attributes that return Java String in the LDAP Java API.

Grantees

A grantee is either an individual user or a group of users. A user can be a member of zero, one, or more directory service groups, and a group can contain zero, one, or more subgroups. (
Tip: Any user account that can successfully log on to a FileNet P8 domain is automatically added to the #AUTHENTICATED-USERS special account, which is an internally managed logical group, the members of which are authenticated user principals.
) A FileNet P8 realm consists of a set of related groups and users. A realm is normally mapped to a directory partition in a directory server. The primary use of a Realm object is to retrieve lists of the groups and users in the realm.

A user account is defined to the Content Engine server by using tools that are provided by the directory service, for example, Microsoft Active Directory, Microsoft Active Directory Application Mode (ADAM), Microsoft Active Directory Lightweight Directory Services (AD LDS), Oracle Directory Server, Novell eDirectory, or Computer Associates (CA) eTrust. A User object exists in the Content Engine API as part of the security interface that allows a particular user to access a Content Engine resource. A Group object represents a set of user accounts. Access rights (permissions) are assigned to individual user accounts and to the groups to which the individual user belongs.

Security on objects, such as folders and documents, can pertain to particular groups. These groups, and the users and subgroups that make up the group's membership, are typically defined and created by a system administrator that uses tools that are provided by the directory service. You cannot call a Content Engine API method to create a new group or user; however, you can instantiate a Group or User object that is defined to your directory service. You can retrieve a collection of groups and a collection of users then retrieve elements from the collections, or you can call methods on the Factory classes for the type of object (group or user) you want to instantiate. You can then call methods on the object to retrieve information about it, such as name and ID.

How your application retrieves user and group information can affect system performance; refer to Role-Based Security for information on performance considerations.

Encryption

When password properties are stored in the Content Engine, they are encrypted by using the Federal Information Processing Standard (FIPS) Advanced Encryption Standard (AES) 128-bit algorithm with the Content Engine server’s master encryption key. The master key for encrypting and decrypting credentials is generated and stored during installation of the Content Engine software. For more information, see Content Engine Encryption for more information. Encryption information is also specified in the CEMPBoot.properties file. (For more information, see the descriptions of the CipherKeyLength, CipherAlgorithm, and EncryptedPassword CEMPBootstrap properties in the Content Engine bootstrap properties topic of the Security section of the Content Engine Administration documentation.)

The actual encryption and decryption of password values is performed on the Content Engine server, by using the Java Cryptography Enhancements (JCE) module that is present in the application server that hosts the Content Engine. The Content Engine can run in FIPS 140-2 enabled mode, but only when a FIPS 140-2 certified JCE provider is configured. To place the Content Engine in FIPS enabled mode, use the IBM WebSphere® 7.0 platform with the IBMJCEFIPS JCE provider.

Security Caching

The IBM FileNet Content Engine has numerous caches that are related to security, some that are associated with the object store and others that are associated with server security configuration. As with other Content Engine caches, most of these caches are based on a least recently used (LRU) algorithm and some also have an associated TTL (time to live). Caches have a configurable maximum entries attribute that defines the maximum number of cached entries allowed. When this value is exceeded, the least recently used elements are removed to make room for the new, more recently used elements. The TTL (if applicable) that is associated with a cache element defines the amount of time that the cached value remains before it is refreshed. TTL values are also configurable. Because characteristics of a cached element can change (for example, when the security permissions on an object get updated), cached values are refreshed periodically to provide a mechanism for those changes to take effect.

  • SecurityDescriptorCache is responsible for managing (caching) security descriptors to reduce database roundtrips. This cache has only a maximum entries attribute (ObjectStore.SecurityDescCacheMaxEntries) and no TTL attribute since security descriptors never change (only new ones are added) so they never become stale and never need to be refreshed. When the maximum entries value of this LRU cache is exceeded, the least recently used elements are removed to make way for more recently used items.
  • ObjectSecurityCache is responsible for managing (caching) the security characteristics that are associated with a given object. This cache is used for security proxy support (the SecurityProxyType constant class). This cache is used when computing inherited security and for Records Management when an object is declared as a record. Any object-valued property with the SecurityProxyType set in the metadata uses this cache when security is computed for the related object. This cache has both a maximum entries attribute (ObjectStore.ObjectSecurityCacheMaxEntries) and a TTL attribute (ObjectStore.ObjectSecurityCacheEntryTTL).
  • MarkingSetCache is responsible for managing (caching) marking sets from the FileNet P8 . Marking sets are domain-wide resources that can be associated with objects in one or more object stores. The marking set cache has both a maximum entries attribute (ServerCacheConfiguration.MarkingSetCacheMaxEntries) and a TTL attribute (ServerCacheConfiguration.MarkingSetCacheEntryTTL). Marking sets are stored in the GCD and any refresh of the GCD refreshes all of the marking sets.
  • SubjectCache is responsible for managing (caching) security principal (JAAS Subject) information. This cache is used by the server's CEWS interface to reduce the number of LDAP authentication requests the server must perform. (All CEWS requests to server processes must be performed by an authenticated user.) The Subject cache has both a maximum entries attribute (ServerCacheConfiguration.SubjectCacheMaxEntries) and a TTL attribute (ServerCacheConfiguration.SubjectCacheEntryTTL). You should always set the TTL to a value that is smaller than the configured credentials expiration time (usually an application server's configuration value).
  • PrincipalCache is responsible for managing (caching) principal information. This cache stores a local copy of the mapping between information about the principal (such as its name and other properties) and the principal’s security ID. Maintaining this information in Principal cache means Content Engine does not have to retrieve the information from the authentication provider every time it needs the information. The PrincipalCache has both a maximum entries attribute (PrincipalCacheMaxEntries) and a TTL attribute (PrincipalCacheEntryTTL).
  • UserTokenCache is responsible for managing (caching) user token information. This cache stores a local copy of the mapping from a security principal (a user or a group) to its list of security IDs (SIDs) used by Content Engine to authorize the principal. The list of security IDs contains the SID of the current user, the SID for each group the user belongs to (either directly, or as the result of being a nested member of the group, indirectly), and the SID of the #AUTHENTICATED-USERS built in group. Maintaining this information in UserToken cache means Content Engine does not have to retrieve the information from the authentication provider every time it needs information about a user. The UserTokenCache has both a maximum entries attribute (UserTokenCacheMaxEntries) and a TTL attribute (UserTokenCacheEntryTTL).

User and Group Caching

For performance reasons, the Content Engine keeps a cached copy of the users, groups, and realms that are returned from the database of your system's configured authentication provider. Cache refresh rates are controlled by cache configuration settings that specify a time to live (TTL) value for cached information. The default values are the following:

  • For the collection of Realms returned by a call to EntireNetwork.get_AllRealms: 12 hours
  • For a User or Group associated with a realm: 1 hour
  • For a Users or Groups collection that is associated with a user or group: 1 hour

The consequences of caching user, group, and realm information can include the following unexpected behaviors:

  • An application might continue to see an object for a user, group, or realm that was deleted since the last cache refresh. This behavior can occur when lists of users, groups, or realms are manipulated.
  • An application might see an exception when it is trying to use a recently deleted user or group as a grantee in an AccessPermissionList collection.
  • An application might not see, and therefore does not use, a recently added user, group, or realm when retrieving collections of these objects.
  • Updates to user and group information (such as a change to the display name) might not be immediately visible.

Security of objects in the Content Engine is not compromised by these consequences.

Because adding and removing groups tends to happen much less frequently than adding and removing users, sites and applications that use mostly groups and not users as security grantees are less affected by the these consequences.

Integrated Logon (SSO)

Integrated logon (also known as single sign-on or SSO) is the feature whereby a user can access multiple systems after being authenticated just one time. The Content Engine server takes advantage of an earlier Windows logon to authenticate a user (that is, establish the user's identity) without requiring the user to provide credentials (such as user name and password) again for each subsequent logon.

Using the SSO support that is provided in FileNet P8 Platform , your custom applications can integrate with any SSO vendor (such as CA/Netegrity or IBM Tivoli®) that provides JAAS-based authentication on the platforms that are supported by FileNet P8 . If an SSO vendor has provided JAAS LoginModules that work with a given application server, FileNet P8 can support that single sign-on solution for Java based applications. There are limitations to this ability to integrate with SSO providers; for a complete list of limitations, see Single Sign-on Integrations via JAAS. Custom applications have the following limitations:

  • JAAS-based SSO integration is only available to Java EE-based clients (clients who are able to perform a JAAS login). These clients include most browser-based clients that work with a Java EE-based presentation tier server.
  • JAAS-based SSO integration does not generally extend to .NET based clients or pure web server-based clients, who are not able to directly take advantage of the JAAS integration. (For these clients, the username/password and Kerberos authentication profiles are supported.)
  • JAAS-based SSO integration is only supported when the Content Engine is configured to run over the EJB transport.

For information about the requirements and configuration steps for clients that use Kerberos as the SSO provider, see Implementing Kerberos.

Object Permissions

Security for an object is specified in terms of access rights. Access rights are permissions that specify operations that the grantee (user or group) is allowed to perform on an object. Access rights are set as a bitmask, where each bit in the mask represents an access right. A grantee does or does not have a particular right, depending on whether the corresponding bit is set or not. Access rights are represented in the APIs as AccessRight constants that identify individual permissions.

A class has default instance permissions in the form of an Access Control List (ACL), a list of grantees and the access rights that each grantee has on objects of that class. An individual entry in the list, specifying a single grantee and its associated access rights, is an Access Control Entry (ACE). When a new object is created, the default instance permissions of the class are assigned to the object, unless the creating application explicitly provides its own ACL.

You can modify or replace an ACL on an object, and any inherited permissions supplement the object's access control entries in the ACL. For example, say that the default ACL of a document object includes a grantee with rights to view properties and content (AccessRight.READ_ACL, AccessRight.READ, and AccessRight.VIEW_CONTENT). You might grant the additional permission of AccessRight.WRITE to allow the grantee to modify the document's properties and view its content.

To determine which access rights are required to perform common actions on Content Engine objects, see Access rights required to take actions.

Retrieving Permissions

To retrieve the basic permissions on an object, call get_Permissions. This method returns an access permission list with all of the grantees with permissions on the object. Each AccessPermission object in the list specifies a grantee (a user or group), the access rights (permissions) associated with the grantee, and whether the grantee is granted or denied the specified access rights on the object.

You can call get_Permissions on most IndependentlyPersistableObject objects.

Note that the Marking interface is the only one with a Permissions property that is not used to calculate effective access of the primary object. For more information, see Marking Object Permissions.

Setting and Checking Permissions

To set permissions on an object, call set_Permissions and pass in a collection of AccessPermission objects. See Setting Permissions for a code example.

To check basic access rights for a user, call getAccessAllowed on an IndependentlyPersistableObject to return a bit mask that represents the current caller's effective access to the object. Then, use AccessRight constants to check permissions. See Checking Permissions for a code example.

Displaying Permissions in a User Interface

For applications that require a user interface (UI) for selecting object permissions, the Content Engine APIs provide the AccessPermissionDescription interface. The interface provides methods that retrieve descriptive information about access rights and access levels that users need in selecting permissions.

To populate a UI with all of the available access rights and levels for an object, you retrieve a collection of access permission descriptions (APDs) from the class of the object type. The collection represents all of the permissions that a user can set for that object type. You then iterate the collection and display the permission type, display name, and descriptive text of each APD.

Important: APDs are strictly intended to provide descriptive information about permissions that are available on Content Engine objects. Never use APDs or AccessLevel constants to set or check permissions in non-interactive code. The values of APDs are subject to change over time and might not accurately reflect your code's original intent. Use only collections of individual access rights to set and check permissions.

See Getting Access Permission Descriptions for a code example.

Role-Based Security

Role-based security means that permissions are based on group membership. Using role-based security provides performance benefits and is recommended over assigning permissions to individual users.

Calling methods that return collections of User and Group objects (such as get_Users on the Group interface and findUsers and findGroups on the Realm interface) involves a lookup operation on the directory server. Response times for the lookup operations that associated with these calls increase with the number of entries to return, and are further degraded when the lookup is performed on a directory server with limited system resources. Because the number of groups in a realm is typically much smaller than the number of users in the realm, group lookups yield better response times than user lookups. For example, when you contruct your application, call Realm.findGroups first and make calls to Group.get_Users only as necessary. When collections are returned from a large directory of groups and users, use the filtering capability that is provided by parameters to the findGroups and findUsers methods to limit the number of items returned.

When get_MemberOfGroups is called on a User or Group object that belongs to a nested set of groups, all groups to which the user or group belongs are returned.

You can restrict a group membership search to search within the realms that are configured in IBM Administration Console for Content Platform Engine by setting the RestrictMembershipToConfiguredRealms property on the DirectoryConfiguration class. When the value of this property is false (the default), the Content Engine server searches the following types of group memberships:

  • Realm-local group memberships.
  • Cross-realm group memberships that are in the configured realms.
  • Cross-realm group memberships that involve realms that are not configured in Administration Console for Content Platform Engine. If the Content Engine server encounters this type of group membership, it logs an error and stops processing the search.

If the value of this property is true, the Content Engine server searches the first two types of group memberships, but ignores the third type. More specifically, it does not generate an error when the group membership search encounters a realm that is not configured in Administration Console for Content Platform Engine. Instead, it writes an INFO level message to the Content Engine server error log, skips this specific group membership, and moves forward. In other words, if this Boolean property is enabled, the Content Engine server ignores any cross-realm group memberships that involve realms that are not configured in Administration Console for Content Platform Engine.

Except for Windows Active Directory Application Mode (ADAM), the RestrictMembershipToConfiguredRealms property is supported in every type of directory service provider that is supported in IBM FileNet Content Engine 4.5. In the case of ADAM, which does not support cross-realm group memberships, the property is retained on the DirectoryConfiguration class for consistency across all supported directory servers, but the setting of the property on a DirectoryConfigurationADAM object has no meaning and is ignored. (Note that RestrictMembershipToConfiguredRealms is specified in the DirectoryConfiguration class, which is inherited by its child classes, such as DirectoryConfigurationADAM.)

There can be security implications if you choose to restrict membership searches to only the realms that are configured in Administration Console for Content Platform Engine. The following scenario is one example: The security administrator configures two Active Directory domains, X and Y. The administrator then configures Group A in Domain X and configures Group A to belong to Group B in Domain Y. Group B is then denied access to Content Engine. As a result, Group A in Domain X is also denied access to Content Engine. The administrator then removes Domain Y from the configuration and sets the DirectoryConfigurationAD.RestrictMembershipToConfiguredRealms to true (that is, use only local group memberships) in Domain X. Now the preconfigured Deny action for Group A is no longer in effect and security might be compromised.

Carefully examine security implications before you choose to ignore cross-realm group memberships on lookup operations.

Security Markings

A security marking is an extra level of security that can be assigned to an object, and is represented by a Marking object. A Marking object combines metadata behavior with access control behavior in a way that allows an object's access control to change by changing a property value. Each marking has a string metadata value that is assigned to a property value when the marking is applied to an object.

A Marking object represents a single item in a marking set. The markings in the marking set define the list of possible values for a single or multivalued property of an object. A marking set is associated with a property on an object class. As an example, in a marking set that is called Security Codes, the individual markings might have string values such as Top Secret, Secret, Confidential. After you assign the Security Codes marking set to a Document object, you can assign one or more of its markings to the document by setting the value of one of its properties. (Note that an object can be assigned only one marking set but multiple markings.) For example, you might assign a value of Top Secret to a custom property called Clearance on a document. After the authorization service evaluates the permissions on a particular object, it also evaluates the markings on the object. A security principal who wants to access that document must have sufficient access from all assigned markings.

You can set multiple values for the Marking property on a new object. If you attempt to create an object, passing in a Marking property value for which the user has been granted Add rights but not Use rights, the method throws an access denied exception.

Creating a Marking Object

Creating marking sets and markings requires FileNet P8 domain administrator access rights. Marking sets and markings are stored in the Content Engine GCD. A marking set is associated with a property on an object class. You cannot create a Marking object by using the Content Engine APIs. However, you can create an instance of a saved Content Engine marking. For a list of ways to instantiate a Marking object and for a list of objects to which you can assign one or more markings, refer to the reference help for the Marking interface. (For information about creating the Content Engine Marking and MarkingSet objects, see the Markings topic in the Content Engine Security documentation.)

From an instance of a Marking object, you can obtain its ID, the ID of its class description, and its display name. In addition, you can call methods that return the marking's value and the set of access rights that are associated with the marking value when the marking is applied. You can also retrieve the marking's constraint mask. The constraint mask is a bit mask that represents the set of access rights that are affected by the marking when it is applied to an object. For information on each of these methods, refer to the online help for the Marking interface. For code examples, refer to Working with Marking Objects.

Active Markings

Any object that can have a marking can be assigned one or more markings. A marking that is assigned to an object is called an active marking. The list of all markings that are assigned to a single object is represented by an ActiveMarkings collection. You cannot create an ActiveMarking object or an ActiveMarkings collection with the Content Java API. However, through an object's ActiveMarkings property you can instantiate an ActiveMarking object from which you can then retrieve the Marking object that is assigned to the object.

Marking Set Caching

Marking set information is cached in much the same manner that user and group information is cached. You can set the refresh time for the cache by using the MarkingSetCacheEntryTTL property, similar to setting refresh times for user and group caches. The cache is also refreshed automatically when a marking set is modified (for example, a new marking is added to the marking set), and the cache is expired when a marking set is deleted.

The marking set cache contains one entry for each defined marking set. (The number of marking values within a marking set is not constrained by the cache size.) As an example, if you set the maximum size of a marking set cache to 100, and you have defined 200 marking sets, only half of the marking sets are loaded in memory. For the best performance, set the maximum size of the marking set cache to be larger than the actual number of marking set instances.

A user's access to an object to which markings have been applied or modified might be affected due to time lags in updating the cache. For more information, see Security cache.

Marking Object Permissions

When retrieving the permissions on a Marking object, note that the permissions returned by the Marking.get_Permissions method do not represent access rights to the Marking object of which they are a part. Rather, they are a collection of access rights that are associated with the marking value and are applied when the marking is assigned to an object. This method also returns special permissions that determine who can apply the marking to and remove the marking from an object. The next few paragraphs describe these special Add, Rremove, and Use permissions.

A user or group must be granted specific permissions to perform operations relevant to a marking that are performed by the authorization service: add, delete, and use a marking. You must have Add permission (AccessRight.ADD_MARKING) to be able to assign (add) a marking to an object, or Remove permission (AccessRight.REMOVE_MARKING) to delete a marking from an object.

The Use permission (AccessRight.USE_MARKING) determines whether a constraint mask is applied when a marking is assigned to an object. If a user is denied the Use access right, then the value of the ConstraintMask property is applied to, and overrides, the object's preliminary Effective Access Mask as computed by the authorization service.

To obtain the access mask for a Marking object based on the current user and the Marking object's permissions, call get_MarkingUseGranted. From the returned value, you can determine if a given user has the appropriate rights to perform marking related operations on an object.

Marking-related Properties

In order to apply a Marking to an object, the MarkingSet that contains the Marking must first be associated with a PropertyDescription from the object’s ClassDescription. This association has the effect of constraining the possible values that can be assigned to the property defined by the PropertyDescription to values associated with the Markings in the Marking Set.

The following topics provide information about specific marking-related properties: MarkingSets, MarkingSet, IsHierarchical, ActiveMarkings, and ConstraintMask.

MarkingSets and MarkingSet Properties

The Domain object's MarkingSets property specifies a collection that contains the MarkingSet objects that are associated with a given domain.

Any object to which a marking can be assigned has a MarkingSet property in its PropertyDescription object. The value of this property defines the possible marking values that can be assigned to the property described by the PropertyDescription.

You can use this property to retrieve a list of Marking objects that can be assigned to an object by a particular security principal. You can display the returned markings in a user interface from which a particular user can make selections. As an example, the MarkingSet property on a marking set that is called Security Codes might contain the markings Top Secret, Secret, and Confidential.

IsHierarchical Property

A MarkingSet object can be defined as nonhierarchical or hierarchical, according to the value of its IsHierarchical property.

A nonhierarchical marking set contains one or more markings, each independent of all others. To compute security access to an object, in most cases the server accesses both the marking set and its contained marking values by ID, which is efficient and fast. However, when a new marking value is added to the marking set, the server examines each value in the marking set to recompute security access, regardless of whether the marking set is nonhierarchical or hierarchical. Having many values in the marking set can impact the performance of this operation.

A hierarchical marking set arranges markings in a simple, single branch hierarchy. Each marking has a superior marking (which must be in the same set), except for the top marking (its superior is null).

The purpose of a hierarchical marking set is to support an order of precedence when evaluating access rights. A marking in a hierarchical marking set explicitly grants access rights to a set of security principals. In addition, it also implicitly grants the same rights for all markings that are inferior to it in the hierarchy. When the marking set is hierarchical, the server must follow the hierarchical path of the marking values in the marking set to compute security access to an object. Having many marking values in the marking set can impact the performance of this operation.

A best practice is to keep the number of marking values small within a marking set, regardless of whether the marking set is defined as hierarchical or nonhierarchical. If you require many marking values, it is more efficient to create more marking sets, each with a smaller number of marking values. An entry is created in the marking set cache for each defined marking set, and each entry takes up a small amount of memory, but the effect on the system is negligible compared with the impact on performance of many marking values in a single marking set.

ActiveMarkings Property

All objects that can have markings have an ActiveMarkings property, which is a list-valued property that returns all ActiveMarking objects that are assigned to the object in question. The list is a Values collection whose elements are the ActiveMarking objects that are assigned to the object. Through an object's ActiveMarkings property, you can get an ActiveMarking object. From that object instance, you can then call getMarking to retrieve the actual Marking object that is assigned to the object in question. For a code sample, refer to Working with Marking Objects.

ConstraintMask Property

An object's ConstraintMask property represents the access rights that are affected when a marking is applied to the object. The constraint mask is specified when the Marking object is created. When the marking is applied to an object, the constraint mask serves to subtract from the object's preliminary Effective Access Mask those access rights that correspond to the bit settings in the mask.

Whether the constraint mask is applied to an object's preliminary Effective Access Mask is determined by whether a security principal is granted or denied the Use access right for a marking. If the security principal is granted Use permission, the constraint mask is not applied. If the security principal is denied Use permission, the object's access control is modified based on the constraint mask. For example, if all bits of the constraint mask are on and a user has been denied the AccessRight.USE_MARKING permission, when the marking is applied to a Document object, the bits in the constraint mask are subtracted from the Document object's preliminary Effective Access Mask. The computed result (the Effective Access Mask) prevents the user from accessing that document.

If you assign a marking to an object, and the marking's permissions have not granted the user or group the Use access right (AccessRight.USE_MARKING), then the rights that are represented by bits in the constraint mask are subtracted (removed) from the preliminary Effective Access Mask that was computed by the authorization service. The computed result of this subtraction is the Effective Access Mask for the object.

You can retrieve the value of the constraint mask by calling get_ConstraintMask on the Marking interface.

Object Security

A newly-created object acquires its default permissions directly from its class. The ClassDescription interface's get_DefaultInstancePermissions method returns the default permissions for an object that belongs to the class. You can use this method to determine if the class's permissions are appropriate for your application or to display the default permissions in a user interface and allow the user to modify the permissions when you are creating a new object of this class.

An object can also acquire permissions through inheritance and from a security policy.

Security Inheritance

Security inheritance is a customizable mechanism for managing access control based on inherited security relationships. The security relationships can be assigned to reflect the relationships inherent in your application object model.

A Document or CustomObject object (any class implementing the Versionable interface) can inherit security based on the following sources:

  • A Folder object that is identified as a security parent in the SecurityFolder property for the child object. Multiple, different security parents (folders) can be specified by using object-valued properties on the child object.
  • A security policy.
  • A combination of security parents and security policy.

A Folder object always inherits its permissions from its parent folder. A Document or CustomObject object's security parent is reflected in the value of its SecurityFolder property. You can indirectly set the SecurityFolder value for an object at the time it is filed into a folder by calling the Folder.file method and specifying DefineSecurityParentage as the value for the defineSecurityParentage parameter. The folder into which the object is filed is then set as the SecurityFolder value.

Note: Although it is assumed that an object's SecurityFolder value identifies the folder in which the object is filed, it is not a constraint. The SecurityFolder value can be any Folder object.

However, setting a child object's SecurityFolder property alone does not guarantee that the child object will inherit a specified parent's permissions: only those permissions that are inheritable to the depth (level) of the child object (in an abstract inheritance tree) are inherited. Use the set_InheritableDepth method on the Permission interface to specify the depth to which a parent object's security can be inherited. Set the method's parameter to a value corresponding to a level in the inheritance chain. The inheritable depth values are as follows:

  • 0 - This object only (no inheritance).
  • 1 - This object and immediate children only. Other positive values greater than 1 indicate the allowed depth of inheritance (for example, 2 indicates that this object, its immediate children and grandchildren only can inherit the permission).
  • -1 - This object and all children (infinite levels deep).
  • -2 - All children (infinite levels deep) but not the object itself.
  • -3 - Immediate children only but not this object. Other negative values less than -3 indicate the allowed depth of inheritance (for example, -4 means only immediate children and grandchildren of the object inherit the permission, but not the object itself).

As the ACE is inherited by an object in a chain of objects, the InheritableDepth property value is decremented.

You can determine the source of an inherited permission by retrieving the value of the Permission object's PermissionSource property, for example, by calling Permission.get_PermissionSource. Permission entries with a source of PARENT (SOURCE_PARENT) have been inherited.

Inheritance of security for any child object is calculated dynamically: whenever an access check is performed on the child object, or the Permissions collection that is associated with the child object is retrieved. The inherited access control entries (ACEs) are not persisted in the child object's access control list, but are calculated from the inheritable ACEs for the security parent that is specified in the child object's SecurityFolder property.

A security parent or parents also can be designated by using object-valued properties. Use the INHERITANCE setting for the SecurityProxyType constant. You can set SecurityProxyType by using PropertyTemplateObject.set_SecurityProxyType.

When the INHERITANCE type of security proxy is used, it is possible to specify multiple security parents for an object. You can do so by assigning SecurityProxyType.INHERITANCE values to more than one object-valued property on the object. The resulting security descriptor for the object is calculated by merging the inheritable ACEs of the different security parents with the child object's persisted ACEs.

For information about security inheritance rules, refer to Understanding security inheritance topic in the Content Engine Security documentation.

Security Policies

Security policies allow greater administrative control over object security than that provided by standard security. For example, instead of an object inheriting its security through a security parent, you can elect to use the security policy feature to assign access rights based on an object's state changes.

Security policies support the following two security management mechanisms:

  • Server-managed versioning state-based security changes
  • Application-managed state-based security changes

Version State Security

Enabling version state security automatically applies access rights to versionable objects (Document and its subclasses) as the object moves from one state to another. This behavior is seen with two-level versioning, in which the expectation is that as a document moves through four pre-defined states, access to that document differs for each state. The four pre-defined document states are: InProcess, Released, Reservation, and Superseded. For example, when a document enters the released state (becomes the current major version), you might want all users to be able to view it, but if the document is superseded by a newer version, you might want only the document owner to be able to view it.

Application-managed State Security

You can also choose application-managed security, in which state based changes to both versionable and nonversionable objects (for example, CustomObject or Folder objects) are applied as the object transitions from one state to another. The definition of a state change in this case is entirely application-defined. For example, the application can define a state change as occurring when some specific period of time has passed since the last modification to the object. As the object undergoes state changes, your application controls access to it by identifying points at which security is changed and then explicitly applying access rights that are specified by a selected security template. This process differs from an application directly modifying access rights at various times in that it provides a level of indirection and abstraction. The application still controls the nature and timing of access right changes, but the specific details of the changes are isolated to security policies.

Security Policy

The security policy is the mechanism for controlling access to an object as its state changes. The security policy is a container that holds a set of security templates. Templates hold a collection of predefined permissions that can be applied to a Document, CustomObject, or Folder object. The template defines the exact security change that occurs when the template is applied to an object.

Security policies are created and a default security policy can be assigned to Document, CustomObject, and Folder classes. (Typically, these tasks are performed by a Content Engine administrator.) An object's security policy is reflected in the value of its SecurityPolicy property. Users with appropriate permissions can remove the security policy from the class, or change the security policy on the class. When a new subclass of one of these classes is created, the subclass inherits the security policy of its parent class. However, after the subclass is successfully created, that security policy can be removed or changed by setting the object's SecurityPolicy property in the same manner as you set any other object-valued property.

Security policies offer flexible control over object security.

  • A single security policy can manage objects of different classes. For example, you can create a single security policy that is assigned to any combination of Document, Folder, and CustomObject classes, or their subclasses.
  • More than one security policy can be used by different groups of objects of the same class. For example, you can create multiple Document objects and assign each a different security policy.
  • A single security policy can be shared by many objects. For example, you can create a single security policy and assign it to zero or more Document, Folder, or CustomObject objects, or any combination of the three object types.

A security policy is made up of a set of security templates, each of which corresponds to an object's state. Each template contains the access rights that are assigned to an object as a result of applying the template. When versionable objects (such as Document) move from one versioning state to another, for example, from InProcess to Released, the appropriate security template is retrieved from the security policy and automatically applied to the object. "Applied" in this context means that the permissions defined in the security template are assigned to the object, replacing any permissions previously inherited from a security template. Your application can also explicitly apply a template to a versionable or nonversionable object. For more information, see Applying a Security Template.

From the Content Engine APIs, you manage and manipulate the security policy through the SecurityPolicy object and SecurityTemplate objects. For more information about these objects, see SecurityPolicy Object and SecurityTemplate Object.

SecurityPolicy Object

A SecurityPolicy object is an independently persistable, subclassable container object for a set of SecurityTemplate objects. Each SecurityPolicy object can contain zero or more application security templates and from zero to four versioning security templates. The SecurityPolicy object's multi-valued, object-valued SecurityTemplates property contains the security templates that are contained in the policy. A SecurityPolicy object can be associated with one or more Document, CustomObject, or Folder objects, or any combination thereof that shares a common access control scheme. Associating a SecurityPolicy object with an object allows the templates that are contained in the policy to be applied to the object. A single SecurityPolicy object can contain versioning security templates, application security templates, or both.

Given the appropriate permissions, you can create a new SecurityPolicy object, or retrieve, change, and save an existing one. You can also:

  • Add new SecurityTemplate objects to the SecurityPolicy object.
  • Delete existing SecurityTemplate objects from the SecurityPolicy object.
  • Modify SecurityTemplate objects that are contained in the SecurityPolicy object.

Modifications to an existing SecurityPolicy object are not propagated to objects that refer to that policy.

For ways to instantiate a SecurityPolicy object, refer to the SecurityPolicy interface description in the reference help.

Security Policy Assignment

A SecurityPolicy object can be associated with a Document, CustomObject, or Folder object by setting the object's SecurityPolicy property. When you create the object, you can assign to it a maximum of one security policy. Multiple security policies are not allowed on a class definition or a single object instance. If you do not assign a security policy to the new object at creation time, the value, if any, specified as the default (in the SecurityPolicy property description of the class) is copied to the object instance. When subclasses of a class that has an associated security policy is created, the new subclass shares the security policy with its parent class.

As a versionable object undergoes versioning state changes, its permissions, based on its security policy, are modified. If the versionable object has no associated security policy, its permissions remain unchanged when its versioning state changes. When you set the SecurityPolicy property of a Document object for the first time, or you change it to refer to a different security policy, the new policy is applied to the current (latest) version of the document in the version series.

An object's security policy can also change when you change the class of a Document, CustomObject, or Folder object. The value for the object's SecurityPolicy property is changed according to the same rules as for other properties. For more information, see the reference help for the changeClass method.

Security Policy Removal

You can remove a security policy from an object, or remove security policy objects from the object store.

To remove a security policy from an object, set the object's SecurityPolicy property to null. This removes from the object all permissions that were inherited from the security policy's templates.

Given the appropriate permissions, you can delete a security policy from the object store. Doing so removes the SecurityPolicy object and all its contained SecurityTemplate objects. You cannot delete a SecurityPolicy object that is in use. A SecurityPolicy object is considered in use if there are any outstanding references to it. Outstanding references include when it is identified as a class default value or when the SecurityPolicy property of at least one Document, CustomObject, or Folder object is set to the SecurityPolicy object you want to delete. When any of the following events occurs on a Document, CustomObject, or Folder object, the associated SecurityPolicy object is no longer be considered to be in use and you can delete it:

  • The object's SecurityPolicy property is changed to reference a different SecurityPolicy object.
  • The object's SecurityPolicy property is set to null.
  • The object itself is deleted.

SecurityTemplate Object

The SecurityTemplate object is a dependently persistable object that contains the permissions that are applied to an object. An instance of this object cannot be created or persisted independently of a parent SecurityPolicy object. (For ways to create a new SecurityTemplate object or retrieve an existing one, refer to the VersioningSecurityTemplate or ApplicationSecurityTemplate interface description in the reference help.) Using the SecurityTemplate object's methods, you set its properties and permissions before you add it to a SecurityPolicy object. The SecurityTemplates property of the SecurityPolicy object reflects the templates that are contained within the policy.

A description of the permissions that the SecurityTemplate object represents can be obtained by getting the value of the object's TemplatePermissionDescriptions property. From this property, you can determine the template's AccessPermissionDescription objects, each of which provides descriptive information for an access right or level. The information, which you can use to populate security editing dialogs in a user interface, consists of the permission's access mask, permission type, and display name.

A SecurityTemplate object can represent either an application security template or a versioning security template. The two types have the same object type, but are differentiated by their class IDs (GUIDs) and by their uses. Class IDs for the security template types are defined by the following constants: APPLICATION_SECURITY_TEMPLATE and VERSIONING_SECURITY_TEMPLATE. (Refer to the FileNet.Api.Constants namespace or filenet.com.api.constants package in the reference help.)

Application Security Template

Use application security templates when you want your application to manage object security as an object's state changes. An application security template is a predefined collection of permissions that can be applied to a Document, CustomObject, or Folder object. An application security template is never automatically applied; it must be explicitly applied to the object.

An application security template's ApplyStateId property associates the template with a particular state that is defined by your application. When the application determines that an object has transitioned to that state, the application can call the applySecurityTemplate method on the object, specifying the value for the applyStateId parameter as either a user-defined GUID or one of the pre-defined versioning state GUIDs. The method uses the GUID to locate and select the appropriate template to apply from those available in the SecurityPolicy object that is associated with the object.

A user or group with permission to modify an object's security (AccessRight.WRITE_ACL) can change an object's security by explicitly applying any of the enabled SecurityTemplate objects that are contained in the SecurityPolicy object.

Versioning Security Template

A versioning security template is used exclusively to support the automatic update of a Document object's permissions as its versioning state changes. A default versioning security template is available for each state through which a document version can transition: InProcess, Released, Reservation, and Superseded. The template's ApplyStateId property contains a value that corresponds to one of the four statically defined GUIDs for each state. The GUIDs are defined as constants in the VersionStatusId class as follows:

  • IN_PROCESS
  • RELEASED
  • RESERVATION
  • SUPERSEDED

When a versionable object's state changes, the template corresponding to the changed state is located from those available in the SecurityPolicy object and is automatically applied to the object.

As an example, when a Document object's version state changes from InProcess to Released, the associated SecurityPolicy object is searched for a versioning security template whose ApplyStateId property is set to VersionStatusId.RELEASED, and the permissions that are defined by that template are automatically applied to the object. If a security template has been previously applied to a versionable object, the permissions in the automatically applied versioning template replace the previously applied permissions.

A user or group with permission to modify an object's security (AccessRight.WRITE_ACL) can change an object's security by explicitly applying any of the enabled SecurityTemplate objects that are contained in the SecurityPolicy object.

Enabling and Disabling Templates

You can optionally disable an individual template in the SecurityPolicy object. Disabling a template sets its IsEnabled property to false. A disabled template remains a part of its SecurityPolicy object container, but cannot be applied to an object. Disabling a template is useful when you are testing or developing security templates that make up a security policy.

Enabled templates of the appropriate type are applied to an object in the following circumstances:

  • Automatically when you create an object instance whose class has a default security policy.
  • Automatically when a versionable object undergoes a versioning state change.
  • When you explicitly call an object's applySecurityTemplate method.
  • When you explicitly call an object's changeClass method.

Applying a Security Template

When the SecurityPolicy property of a versionable object is set for the first time or changed to refer to a different SecurityPolicy object, the SecurityPolicy object is searched for a template that corresponds to the current version status of the document, and the template is applied (that is, the permissions that are defined in the template are assigned to the object).

An application can modify the existing security on an object by calling the applySecurityTemplate method on the Document, CustomObject, or Folder interfaces. This method applies an individual security template, which is specified by the applyStateId parameter, to the object. Using the parameter value, the method locates the SecurityTemplate object whose ApplyStateId property corresponds to the value contained in the parameter.

When the method locates the template, it applies it to the object (that is, the permissions that are defined in the template are assigned to the object). Permissions from the template are applied to the object in the following order:

  • Old permissions that are inherited from the object's security policy are deleted.
  • If the associated SecurityPolicy object's PreserveDirectPermissions property is set to false, the method deletes noninherited permissions (that is, those permissions that have been directly set on the object) and retains only inherited permissions; if set to true, the method retains the noninherited (directly set) permissions.
  • New permissions from the SecurityTemplate are added to existing permissions that were inherited from the object's security parent and to any existing noninherited permissions.