This section summarizes the configuration issues when integrating Stardust into an existing security infrastructure. For an in-depth discussion of the underlying concepts, see the Programming Guide.
Note: Server side
properties described in the configurations below are meant to be set in the server side carnot.properties.
Client side properties have to be
set in the client side carnot.properties.
Authentication can be done in one of the following modes:
The following table summarizes the different authentication options.
| Custom Registry | Spring Local Mode | Client Bean Factory | |
|---|---|---|---|
| Internal Login | no | yes | no |
| JAAS Login | yes | yes | no |
Authorization in Stardust, i.e. the assignment of participants (roles/organizations) to users is normally stored in the audit trail. If an external user registry is used the authorization information has to be replicated from the external registry every time a login is done. This role mapping logic has to be implemented by providing an implementation of the
org.eclipse.stardust.engine.core.spi.security.DynamicParticipantSynchronizationProvider
interface. The details for implementing a synchronization provider can be found in the Programming Guide.
The modes for authentication and authorization are both internal per default. They can
be changed in the server-side carnot.properties file via the following
properties:
In case the Security.Authorization.Mode has been set to a different
value then internal, authorization will be external. The Synchronization provider
needs to be in place and configured. If Security.Authentication.Mode has
been set to a different value then internal, authentication will be external
and the Login Provider needs to be in place and configured.
The following scenarios are possible:
| Authentication | Authorization | Behavior |
|---|---|---|
| internal | internal | Users and grants are handled completely internally. |
| internal | external | Users are handled internally, grants are handled externally. |
| external | internal | Users are handled externally, grants are handled internally. |
| external | external | Users and grants are handled completely externally. |
Note
A SynchronizationProvider is always required as soon as Authentication OR
Authorization are configured in any external mode.
Internal authentication mode is turned on by default when no security related properties are explicitly set. It always uses the audit trail database as authentication and authorization source. You can document the use of internal authentication explicitly by setting the following property on the server:
Security.Authentication.Mode = internal
The following table summarizes other server side configuration options for internal authentication:
| Property | Range/Default Value | Remarks |
|---|---|---|
Security.Authentication.Mode |
String / internal | internal authentication mode |
Security.Authentication.MaximumNumberLoginRetries |
integer / 3 | A re-login try threshold. If exceeded the account is temporarily disabled |
Security.Authentication.InvalidationTimeInMinutes |
integer / 1 min | The time an account is disabled after unsuccessful login |
Please note that in case you like to perform a stateless deployment for internal authentication you have to adjust some settings in your deployment descriptor. Please refer to the section Stateless Bean Deployment for Internal Authentication of the chapter Deploying Stardust Components to an EJB Application Server in the Deployment Guide for detailed information.
Server side JAAS Authentication is set by:
Security.Authentication.Mode = jaas
Additionally, you have to provide the following properties:
| Property | Range / Default Value | Remarks |
|---|---|---|
Security.Authentication. |
String / - |
The JAAS login configuration name |
Security.Authentication.PrincipalClass |
String / - |
The class name of the principal to use from the returned JAAS Subject |
You also have to set up a login configuration in the server configuration itself. Please refer to your application server security documentation for detailed information on how to do this. Note, that the exact method of authentication tried depends on the credentials present in the JAAS subject and the JAAS configuration set by the application.
The JAAS authentication mode is transparent to the client. No configuration is necessary.
Participant synchronization has to be done if authentication is done against an
authentication source different from the audit trail database. The Stardust Process Engine
then has to synchronize the participant mappings at login time. The configuration to be
provided is the name of the SynchronizationProvider to use, and probably provider
specific settings:
Security.Authorization.SynchronizationProvider = classname
To control the frequency of participant synchronization, Stardust evaluates the property:
Security.Authorization.SynchronizationStrategy = classname
The strategy implementation has to be an implementation of the interface:
org.eclipse.stardust.engine.core.spi.security.DynamicParticipantSynchronizationStrategy
By implementing this interface it is possible to tell the engine if a specific dynamic participant's external representation is likely to have been, thus requiring a new synchronization operation. By default the class:
org.eclipse.stardust.engine.core.spi.security.TimebasedSynchronizationStrategy
is used, which itself by default synchronizes any participant only every 10 seconds. This delay may be configured by setting the properties:
Security.Authorization.TimebasedSynchronizationStrategy.UserSyncTimeout
and
Security.Authorization.TimebasedSynchronizationStrategy.UserGroupSyncTimeout
to the desired number of seconds.
If you want to invalidate a user or usergroup, which does not exist in external registry, you can set the following property:
Security.Authorization.InvalidateNonexistingParticipants
The validTo property of the non-existing user or usergroup will then be set to current date.
To enable tracing for user or usergroup synchronization with external registry evaluate the following property:
Security.Authorization.TraceSynchronization
Participant synchronization is transparent to Stardust clients. It only has to be configured on the server side.
If you want to enforce Java 2 Security in your application server you have to relax somehow the permissions mandated in the J2EE specification to allow access to Stardust resources. Also, Stardust uses advanced Java reflection you have to permit.
Here are the permissions you have to set to operate Stardust:
java.io.FilePermission "carnot-engine.jar" "read";
to read resources from the Stardust jar:
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
permission java.lang.RuntimePermission "accessDeclaredMembers";
to allow advanced Java reflection.
Dependent on the JAXP implementation your application server is using you may need additional permissions, like
permission:
java.io.FilePermission "xalan.jar", "read";
If you intend to use Stardust mail functionality (notifications or triggers) you also have to relax the permissions to get access to JDK specific mail resources.
Stardust provides security examples with source code for example implementations. Refer to the Examples section for details.
Stardust provides an LDAP synchronization example, which is useful if you have to synchronize against an LDAP repository and if you can express the user-to-participant mapping by an LDAP search filter.
You can download this example here:
This provider can be configured using the following properties:
| Property | Range/ Default Value |
Remarks |
|---|---|---|
LDAPSynchronization.ServerName |
Hostname / - | The host name of the LDAP server to connect |
LDAPSynchronization.ServerPort |
Port number / 389 | The port number to connect |
LDAPSynchronization.RootDN |
LDAP distinguished name | The distinguished name where all operations are relative to |
LDAPSynchronization.BindMode |
'anonymous' or 'dedicated' /'anonymous' | Flag indicating whether to connect anonymously |
LDAPSynchronization.BindUserDN |
String | User DN to use for connecting if bind mode is dedicated |
LDAPSynchronization.BindPassword |
String | Password to use for connecting if bind mode is dedicated |
LDAPSynchronization.SearchTimeLimit |
Integer / 0 (unlimited) |
The time limit for searches in milliseconds |
LDAPSynchronization.UserFilter |
LDAP search filter | The search filter to get user information for a principal name. The
wildcard %v is used to include the principal name. |
LDAPSynchronization.ParticipantFilter |
LDAP search filter | The search filter to get the participants for a principal name. The
wildcard %v is used to include the principal name. |
LDAPSynchronization. |
LDAP attribute name/'cn' |
The attribute name for getting the Stardust participant ID from a found participant |
As an example here is a configuration which:
uid attribute equal to the principal
namecn attribute of a participant
match (because this is the default of the ParticipantNamingAttribute not
provided here):Security.Authorization.SynchronizationProvider = org.eclipse.stardust.examples.authorization.ldap.LDAPSynchronizationProvider
LDAPSynchronization.ServerName=ldap.de.carnot.ag LDAPSynchronization.RootDN=dc=de,dc=carnot,dc=ag,dc=test LDAPSynchronization.UserFilter="(&(uid=%v)(objectclass=inetOrgPerson)) LDAPSynchronization.ParticipantFilter=(&(objectClass=groupOfUniqueNames)(uniqueMember=uid=%v*))
For a WebLogic authentication example, download the following zip file:
This example provides a secure session factory for WebLogic, that you can
use by setting the property Secure.Session.Factory in your
carnot.properties file:
Secure.Session.Factory = org.eclipse.stardust.examples.authentication.weblogic.WeblogicSecureSessionFactory
For a WebSphere authentication example, download the following zip file:
This example provides a secure session factory and a credential provider
for WebSphere, that you can
use by setting the properties Secure.Session.Factory and
Credential.Provider in your
carnot.properties file:
Credential.Provider = org.eclipse.stardust.examples.authentication.websphere.WASCredentialProvider Secure.Session.Factory = org.eclipse.stardust.examples.authentication.websphere.WASSecureSessionFactory
The following table shows the service operations provided by Stardust depending on the model element and the permission to be used:
| Model Element | Permission/Default Participant | Service Operations concerned |
|---|---|---|
| Model | Deploy and Modify Process Model/Administrator | AdministrationService.deployModel(String model, int predecessorOID) AdministrationService.deployModel(String model, String configuration, int predecessorOID, Date validFrom, Date validTo, String comment, boolean disabled, boolean ignoreWarnings) (deprecated) AdministrationService.deployModel(List<DeploymentElement> paramList, DeploymentOptions paramDeploymentOptions) AdministrationService.overwriteModel(String model, int modelOID) (deprecated) AdministrationService.overwriteModel(String model, String configuration, int modelOID, Date validFrom, Date validTo, String comment, boolean disabled, boolean ignoreWarnings) (deprecated) AdministrationService.overwriteModel(DeploymentElement deploymentElement, int modelOID, DeploymentOptions options) |
| Model | Modify Audit Trail Content/Administrator | AdministrationService.cleanupRuntime(boolean keepUsers) AdministrationService.cleanupRuntimeAndModels() AdministrationService.setPasswordRules(PasswordRules rules) AdministrationService.deleteProcesses(List<Long> piOids) AdministrationService.startProcess(long modelOID, String id, Map<String, ?> data, boolean synchronously) AdministrationService.createProcessInstanceLinkType(String id, String description) |
| Model | Modify Audit Trail Statistics | AdministrationService.writeLogEntry(LogType logType, ContextKind contextType, long contextOid,
String message, Throwable throwable) WorkflowService.writeLogEntry(LogType logType, ContextKind contextType, long contextOid, String message, Throwable throwable) |
| Model | Run Recovery/Administrator | AdministrationService.recoverProcessInstance(long oid) AdministrationService.recoverProcessInstances(List<Long> oids) AdministrationService.recoverRuntimeEnvironment() |
| Model | Manage Daemons/Administrator | AdministrationService.getDaemon(String daemonType, boolean acknowledge) AdministrationService.startDaemon(String daemonType, boolean acknowledge) AdministrationService.stopDaemon(String daemonType, boolean acknowledge) AdministrationService.getAllDaemons(boolean acknowledge) |
| Model | Control Process Engine/Administrator | AdministrationService.flushCashes |
| Model | Obtain Audit Trail Statistics/Administrator | AdministrationService.getAuditTrailHealthReport() AdministrationService.getAuditTrailHealthReport(boolean countOnly) QueryService.getLogEntriesCount(LogEntryQuery query) QueryService.findFirstLogEntry(LogEntryQuery query) QueryService.getAllLogEntries(LogEntryQuery query) |
| Model | Obtain User Data/Administrator | QueryService.getAllUserGroups(UserGroupQuery query) QueryService.getAllUsers(UserQuery query) QueryService.getUserGroupsCount(UserGroupQuery query) QueryService.getUsersCount(UserQuery query) QueryService.findFirstUser(UserQuery query) QueryService.findFirstUserGroup(UserGroupQuery query) UserService.getUser(String account) UserService.getUser(String realm, String account) UserService.getUser(long userOID) UserService.getUserGroup(String id) UserService.getUserGroup(long oid) UserService.getUserRealms() |
| Model | Modify User Data/Administrator |
UserService.modifyUser(User user) UserService.modifyUser(User user, boolean generatePassword) UserService.createUser(String account, String firstName, String lastName, String description, String password, String eMail, Date validFrom, Date validTo) UserService.createUser(String realm, String account, String firstName, String lastName, String description, String password, String eMail, Date validFrom, Date validTo) UserService.invalidateUser(String account) UserService.invalidateUser(String realm, String account) UserService.createUserGroup(String id, String name, String description, Date validFrom, Date validTo) UserService.modifyUserGroup(UserGroup userGroup) UserService.invalidateUserGroup(String id) UserService.invalidateUserGroup(long oid) UserService.createUserRealm(String id, String name, String description) UserService.dropUserRealm(String id) |
| Model | Obtain Model Data/All | QueryService.getProcessDefinition(long modelOID, String id) QueryService.getProcessDefinition(String id) QueryService.getProcessDefinitions(ProcessDefinitionQuery query) QueryService.getModel(long modelOID) QueryService.getModel(long modelOID, boolean computeAliveness) QueryService.getModels(DeployedModelQuery query) QueryService.getModelAsXML(long modelOID) QueryService.getModelDescription(long modelOID) QueryService.getActiveModel() (deprecated) QueryService.getActiveModelDescription() QueryService.getAllData(DataQuery query) QueryService.getAllProcessDefinitions() QueryService.getAllProcessDefinitions(long modelOID) QueryService.getAllAliveModelDescriptions() QueryService.getAllParticipants() QueryService.getAllParticipants(long modelOID) QueryService.getParticipant(long modelOID, String id) QueryService.getAllModelDescriptions() QueryService.wasRedeployed(long modelOid, int revision) QueryService.getParticipant(String id) QueryService.getSchemaDefinition(long modelOID, String id) WorkflowService.getStartableProcessDefinitions() WorkflowService.getModel() (deprecated) |
| Model | Read Departments | AdministrationService.getDepartment(long oid) QueryService.findAllDepartments(DepartmentInfo department, OrganizationInfo organization) |
| Model | Spawn Subprocess Instance | WorkflowService.spawnSubprocessInstance(long parentProcessInstanceOid,
String spawnProcessID, boolean copyData, Map<String, ? > data) WorkflowService.spawnSubprocessInstances(long parentProcessInstanceOid, List<SubprocessSpawnInfo> subprocessSpawnInfo) |
| Model | Spawn Peer Process Instance | WorkflowService.spawnPeerProcessInstance(long processInstanceOid,
String spawnProcessID, boolean copyData, Map<String, ? extends Serializable> data,
boolean abortProcessInstance, String comment) WorkflowService.spawnPeerProcessInstance(long processInstanceOid, String spawnProcessID, SpawnOptions options) |
| Model | Join Process Instance | WorkflowService.joinProcessInstance(long processInstanceOid, long targetProcessInstanceOid, String comment) |
| Model | Create Case | WorkflowService.createCase(String name, String description, long[] memberOids) |
| Model | Save own User Scope Preferences | AdministrationService.savePreferences(Preferences preferences) AdministrationService.savePreferences(List<Preferences> preferenceList) |
| Model | Save own Partition Scope Preferences | AdministrationService.saveConfigurationVariables(ConfigurationVariables configurationVariables, boolean force) AdministrationService.setGlobalPermissions(RuntimePermissions permissions) |
| Model | Modify Departments | AdministrationService.createDepartment(String id, String name, String description, DepartmentInfo parent, OrganizationInfo organization) AdministrationService.modifyDepartment(long oid, String name, String description) AdministrationService.removeDepartment(long oid) |
| Model | Deploy Runtime Artifact | AdministrationService.deployRuntimeArtifact(RuntimeArtifact runtimeArtifact) AdministrationService.overwriteRuntimeArtifact(long oid, RuntimeArtifact runtimeArtifact) AdministrationService.deleteRuntimeArtifact(long oid) |
| Model | Read Runtime Artifact | AdministrationService.getRuntimeArtifact(long oid) AdministrationService.getSupportedRuntimeArtifactTypes() QueryService.getRuntimeArtifact(long oid) QueryService.getRuntimeArtifacts(DeployedRuntimeArtifactQuery query) |
| Model | Manage Deputies | UserService.getDeputies(UserInfo user) UserService.getUsersBeingDeputyFor(UserInfo deputyUser) UserService.addDeputy(UserInfo user, UserInfo deputyUser, DeputyOptions options) UserService.modifyDeputy(UserInfo user, UserInfo deputyUser, DeputyOptions options) UserService.removeDeputy(UserInfo user, UserInfo deputyUser) |
| Process Definition | Start Process/All | WorkflowService.startProcess(String id, Map data, boolean synchronously) WorkflowService.startProcess(String id, StartOptions options) |
| Process Definition | Abort Process Instances/Administrator | AdministrationService.abortProcessInstance(long oid) WorkflowService.abortProcessInstance(long processInstanceOID) |
| Process Definition | Read Process Instance Data/Administrator | QueryService.getAllProcessInstances(ProcessInstanceQuery query) QueryService.findFirstProcessInstance(ProcessInstanceQuery query) QueryService.getProcessInstancesCount(ProcessInstanceQuery query) WorkflowService.getProcessInstance(long processInstanceOID) WorkflowService.getInDataPath(long processInstanceOID, String id) WorkflowService.getInDataPaths(long processInstanceOID, Set<String> ids) WorkflowService.setOutDataPath(long processInstanceOID, String id, Object object) WorkflowService.setOutDataPaths(long processInstanceOID, Map<String, ?> values) WorkflowService.getProcessResults(long oid) |
| Process Definition | Modify Process Instances | AdministrationService.setProcessInstancePriority(long oid, int priority) AdministrationService.setProcessInstancePriority(long oid, int priority, boolean propagateToSubProcesses) |
| Process Definition | Modify Process Attributes | WorkflowService.setProcessInstanceAttributes(ProcessInstanceAttributes attributes) |
| Process Definition | Manage Event Handlers/Administrator | WorkflowService.getProcessInstanceEventHandler(long processInstanceOID,
String handler) WorkflowService.bindProcessEventHandler(long processInstanceOID, EventHandlerBinding eventHandler) WorkflowService.bindProcessEventHandler(long processInstanceOID, String handler) WorkflowService.unbindProcessEventHandler(long processInstanceOID, String handler) |
| Process Definition | Modify Case | WorkflowService.joinCase(long caseOid, long[] memberOids) WorkflowService.leaveCase(long caseOid, long[] memberOids) WorkflowService.mergeCases(long targetCaseOid, long[] sourceCaseOids, String comment) |
| Data | Read Data Values/All | QueryService.getAllBusinessObjects(BusinessObjectQuery query) |
| Data | Modify Data Values | QueryService.createBusinessObjectInstance(String qualifiedBusinessObjectId, Object initialValue) QueryService.updateBusinessObjectInstance(String qualifiedBusinessObjectId, Object newValue) QueryService.deleteBusinessObjectInstance(String qualifiedBusinessObjectId, Object primaryKey) |
| Data | Modify DMS Data | DocumentManagementService.createDocument(String folderId, DocumentInfo document) DocumentManagementService.createDocument(String folderId, DocumentInfo document, byte[] content, String encoding) DocumentManagementService.versionDocument(String documentId, String versionLabel) DocumentManagementService.versionDocument(String documentId, String versionComment, String versionLabel) DocumentManagementService.removeDocumentVersion(String documentId, String documentRevisionId) DocumentManagementService.moveDocument(final String documentId, final String targetPath) DocumentManagementService.updateDocument(Document document, boolean createNewRevision, String versionLabel, boolean keepLocked) DocumentManagementService.updateDocument(Document document, boolean createNewRevision, String versionComment, String versionLabel, boolean keepLocked) DocumentManagementService.updateDocument(Document document, byte[] content, String encoding, boolean createNewRevision, String versionLabel, boolean keepLocked) DocumentManagementService.updateDocument(Document document, byte[] content, String encoding, boolean createNewRevision, String versionComment, String versionLabel, boolean keepLocked) DocumentManagementService.requestDocumentContentUpload(String documentId) DocumentManagementService.removeDocument(String documentId) DocumentManagementService.createFolder(String parentFolderId, FolderInfo folder) DocumentManagementService.updateFolder(Folder folder) DocumentManagementService.removeFolder(String folderId, boolean recursive) DocumentManagementService.setPolicy(String resourceId, AccessControlPolicy policy) DocumentManagementService.migrateRepository(int batchSize, boolean evaluateTotalCount) DocumentManagementService.migrateRepository(int batchSize, boolean evaluateTotalCount, String repositoryId) |
| Activity | Perform Activity Permission/Implicitly via performer assignment | WorkflowService.getActivityInstance(long activityInstanceOID) WorkflowService.activate(long activityInstanceOID) WorkflowService.activateAndComplete(long activityInstanceOID, String context, Map outData) WorkflowService.activateAndComplete(long activityInstanceOID, String context, Map outData, int flags) WorkflowService.activateNextActivityInstance(long activityInstanceOID) WorkflowService.activateNextActivityInstanceForProcessInstance(long processInstanceOID) WorkflowService.complete(long activityInstanceOID, String context, Map outData) WorkflowService.complete(long activityInstanceOID, String context, Map outData, int flags) WorkflowService.getInDataValue(long activityInstanceOID, String context, String id) WorkflowService.getInDataValues(long activityInstanceOID, String context, Set<String> ids) WorkflowService.performAdHocTransition(long activityInstanceOid, TransitionTarget target, boolean complete) WorkflowService.suspend(long activityInstanceOID, ContextData outData) WorkflowService.suspendToDefaultPerformer(long activityInstanceOID) WorkflowService.suspendToDefaultPerformer(long activityInstanceOID, String context, Map outData) WorkflowService.suspendToUser(long activityInstanceOID) WorkflowService.suspendToUser(long activityInstanceOID, String context, Map outData) WorkflowService.suspendToParticipant(long activityInstanceOID, String participant) WorkflowService.suspendToParticipant(long activityInstanceOID, String participant, String context, Map outData) WorkflowService.suspendToParticipant(long activityInstanceOID, ParticipantInfo participant, ContextData outData) WorkflowService.suspendToUser(long activityInstanceOID, long userOID) WorkflowService.suspendToUser(long activityInstanceOID, long userOID, String context, Map outData) |
| Activity | Delegation to other users | WorkflowService.delegateToDefaultPerformer(long activityInstanceOID) WorkflowService.delegateToParticipant(long activityInstanceOID, String performer) WorkflowService.delegateToParticipant(long activityInstanceOID, ParticipantInfo participant) WorkflowService.delegateToUser(long activityInstanceOID, long userOID) WorkflowService.hibernate(long activityInstanceOID) WorkflowService.hibernate(long activityInstanceOID) |
| Activity | Manage Event Handlers/Administrator | WorkflowService.getActivityInstanceEventHandler(long activityInstanceOID,
String handler) WorkflowService.bindActivityEventHandler(long activityInstanceOID, EventHandlerBinding eventHandler) WorkflowService.bindActivityEventHandler(long activityInstanceOID, String handler) WorkflowService.unbindActivityEventHandler(long activityInstanceOID, String handler) |
| Activity | Read Activity Instance Data/All | QueryService.findFirstActivityInstance(ActivityInstanceQuery query) QueryService.getAllActivityInstances(ActivityInstanceQuery query) QueryService.getActivityInstancesCount(ActivityInstanceQuery query) QueryService.getAuditTrail(long processInstanceOID) WorkflowService.getActivityInstance(long oid) |
| Activity | Modify Attributes | WorkflowService.setActivityInstanceAttributes(ActivityInstanceAttributes attributes) |
| Activity | Abort Activity Instances | WorkflowService.abortActivityInstance(long oid) WorkflowService.abortActivityInstance(long oid, AbortScope abortScope) |
| Workitem | Perform Activity | WorkflowService.activateNextActivityInstance(WorklistQuery query) |
| Workitem | ReadActivityInstanceData | WorkflowService.getWorklist(WorklistQuery paramWorklistQuery) |
For a detailed description on the permissions for specific services, refer to chapter Declarative Security Usage in Stardust Services API in the Programming Guide.
The grant OWNER is either the user, the user group,
or the model participant that is currently assigned as performer of
an activity instance. The following methods of the WorkflowService are restricted
to the OWNER by the means of the activity.performActivity
permission, which is fixed and cannot be changed by the modeler:
activateactivateAndCompletecompletegetInDataValuegetInDataValuesIf the current user does not qualify as an OWNER of the activity instance, an AccessForbiddenException will be thrown.
The following two methods require the current user to become the OWNER of the next activity instance:
activateNextActivityInstanceactivateNextActivityInstanceForProcessInstanceIf that is not
possible, because the permission is denied, a value of null
is returned and no authorization specific exception will be thrown.
The method AdministrationService.forceCompletion is
restricted to the Administrator by the means of the
activity.performActivity permission, which is fixed and cannot
be changed by the modeler.
If the current user does not qualify as an Administrator, an AccessForbiddenException will be thrown.