Table of Contents

Configuration - backend

The application uses a Spring boot configuration in the application.properties files. All the configuration items which are used solely for idm begin with idm. prefix. The configuration items from the file can be overloaded through a setting agenda in the gui ⇒ a server restart isn't needed for changing the configuration with idm. prefix, which was one of the main goals. The configuration is saved in the database. Use ConfigurationService for reading and saving configuration items.

Naming conventions of the configuration items in idm:

Cache is used for reading configuration values - default spring boot cache (ConcurrentHashMap) is configured for now. Value in cache is cleared by an active (save, delete) operation.

Configure environment properties

Application profiles

We are using Spring profiles: Doc.

Start server under defined profile (add JAVA_OPTS parameters):

-Dspring.profiles.active=production
Configured devstack profiles

External configuration

External configuration uses Spring: Doc.

Start server with external path to configuration (add JAVA_OPTS parameters):

--spring.config.location=classpath:/default.properties,classpath:/override.properties

Environment properties

To prevent application startup fails due to Flyway error, property -Djava.util.Arrays.useLegacyMergeSort=true has to be added into environment properties. If property is not set, then application can fail on error:
Error creating bean with name 'flywayCore' defined in class path resource [eu/bcvsolutions/idm/core/config/flyway/CoreFlywayConfig.class]: 
Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: Comparison method violates its general contract!

Add JAVA_OPTS parameters:

-Djava.util.Arrays.useLegacyMergeSort=true

Configuration items

Application/ Server

In the application profile (application.properties) and overloadable via ConfigurationService.

# Application stage (development, test, production (default))
idm.pub.app.stage=
# Application instance / server id - is used for scheduler etc.
# Should be defined in property file only
idm.pub.app.instanceId=idm-primary
# Enable forest index for tree structures
idm.sec.app.forest.index.enabled=true
# global date format on BE. Used in notification templates, logs, etc. FE uses localization key 'core:format.date'.
idm.pub.app.format.date=dd.MM.yyyy
# global datetime format on BE. Used in notification templates, logs, etc. FE uses localization key 'core:format.datetime'.
idm.pub.app.format.datetime=dd.MM.yyyy HH:mm
# create demo data at application start
idm.sec.core.demo.data.enabled=true
# demo data was created - prevent to create demo data duplicitly
idm.sec.core.demo.data.created=false

Jpa

In the application profile (application.properties)

# audit table suffix
spring.jpa.properties.org.hibernate.envers.audit_table_suffix=_a
# modified flag for all audited columns
spring.jpa.properties.org.hibernate.envers.global_with_modified_flag=true
# prevent to modify attributes created, creator etc.
spring.jpa.properties.hibernate.ejb.interceptor=eu.bcvsolutions.idm.core.model.repository.listener.AuditableInterceptor
# enable / disable audit (envers)
spring.jpa.properties.hibernate.listeners.envers.autoRegister=true
 
#
# DB ddl auto generation by hibernate is disabled - flyway database migration is used
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=none
#
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:postgresql://localhost:5432/bcv_idm_storage
spring.datasource.username=*****
spring.datasource.password=*****
spring.datasource.driver-class-name=org.postgresql.Driver
# test connection, when is used from pool (reconnect after db is restarted)
spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1

JNDI datasource

Firstly is needed to configure JNDI resource in the J2EE server. Here is a configuration snippet for Tomcat. It assumes PostgreSQL as the database:

<Context antiJARLocking="true" path="/idm">
	<Resource 
	    name="PostgresDS" 
	    auth="Container" 
	    type="javax.sql.DataSource" 
	    username="*****" 
	    password="*****"
	    driverClassName="org.postgresql.Driver"
	    url="jdbc:postgresql://localhost:5432/bcv_idm_storage"
	    maxActive="8"
            maxIdle="4"/>
</Context>

In the application profile (application.properties), update datasource properties:

# JNDI location of the datasource. Class, url, username & password are ignored when set.
spring.datasource.jndi-name=PostgresDS

In logback-spring.xml configuration (by profile, if db appender is used), update datasource properties:

...
<springProperty name="spring.datasource.jndi-name" source="spring.datasource.jndi-name"/>
 
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
	<connectionSource class="ch.qos.logback.core.db.JNDIConnectionSource">
		<!-- please note the "java:comp/env/" prefix -->
		<jndiLocation>java:comp/env/${spring.datasource.jndi-name}</jndiLocation>
	</connectionSource>
</appender>
...

Using SSL

In the application profile (application.properties)

Update datasource properties:

# add ssl usage flag, see https://jdbc.postgresql.org/documentation/head/connect.html
spring.datasource.url=jdbc:postgresql://localhost:5432/bcv_idm_storage?ssl=true

Attachment storage

DefaultAttachmentManager stores binary files on file system. Binary files can be attached to any entity, which implements AttachableEntity interface, read more.

In the application profile (application.properties) and overloadable via ConfigurationService.

#
## Attachment manager
#
# attachments will be stored under this path.
# new directories for attachment will be created in this folder (permissions has to be added)
# System.getProperty("user.home")/idm_data will be used if no path is given
# idm.sec.core.attachment.storagePath=/opt/data
#
# temporary files for attachment processing (e.g. temp files for download / upload)
# getStoragePath()/temp will be used if no path is given
# idm.sec.core.attachment.tempPath=/opt/data/temp
#
# temporary file time to live in milliseconds
# older temporary files will be purged, default 14 days
idm.sec.core.attachment.tempTtl=1209600000

Activiti workflow

# String boot properties for Activiti workflow engine
# https://github.com/Activiti/Activiti/blob/master/modules/activiti-spring-boot/spring-boot-starters/activiti-spring-boot-starter-basic/src/main/java/org/activiti/spring/boot/ActivitiProperties.java
# let activiti to manage their schema
spring.activiti.databaseSchemaUpdate=true
# disable automatic jpa entities persisting - dto usage is prefered
spring.activiti.jpaEnabled=false
# Automatic process deployment
spring.activiti.checkProcessDefinitions=true
# path to automatically deployed definitions - should be the same in all modules
# more locations can be given e.g. classpath*:eu/bcvsolutions/idm/workflow/,classpath:external/config/wf
# resources in the latest location has the highest priority (last wins) - workflow definitions are prioritized by file name, don't change definition's file name, when you want to override some core workflow definition.
# put resource, which has to override some core resource to last location
spring.activiti.processDefinitionLocationPrefix=classpath*:eu/bcvsolutions/idm/workflow/
# definitions name pattern - subfolders can be used
spring.activiti.processDefinitionLocationSuffixes=**/**.bpmn20.xml

Security

In the application profile (application.properties) and overloadable via ConfigurationService.

# allowed origins for FE
# the first value is used as frontend url to notification templates
idm.pub.security.allowed-origins=http://localhost:3000,http://localhost
# auth token
# - expiration in milis
idm.sec.security.jwt.expirationTimeout=36000000
# - secret jwt password
idm.sec.security.jwt.secret.token=idmSecret
# - extend JWT token expiration period on each successful request
idm.sec.security.jwt.token.extend.expiration=true
# recaptcha
# - recaptchaservice endpoint 
idm.sec.security.recaptcha.url=https://www.google.com/recaptcha/api/siteverify
# - secret key, can be generated here https://www.google.com/recaptcha/admin
# - test secret key: https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha-v2-what-should-i-do
idm.sec.security.recaptcha.secretKey=xxx

Allowed-origins defines, which resources can use backend API methods. e.g. When there is a web server serving as reverse proxy on the same server as BE, the http://localhost:3000 may be the right value.

Flyway

In the application profile (application.properties)

# Enable flyway migrations. 
# @see https://proj.bcvsolutions.eu/ngidm/doku.php?id=navrh:databazove_scripty
flyway.enabled=false

Module configuration (flyway-core.properties)

## Core Flyway configuration
#
# Whether to automatically call baseline when migrate is executed against a non-empty schema with no metadata table. 
# This schema will then be baselined with the baselineVersion before executing the migrations. 
# Only migrations above baselineVersion will then be applied.
# This is useful for initial Flyway production deployments on projects with an existing DB.
# Be careful when enabling this as it removes the safety net that ensures Flyway does not migrate the wrong database in case of a configuration mistake!
flyway.core.baselineOnMigrate=true
#
# The name of Flyway's metadata table (default **schema_version**).
# By default (single-schema mode) the metadata table is placed in the default schema for the connection provided by the datasource.
flyway.core.table=idm_schema_version_core
#
# Comma-separated list of locations to scan recursively for migrations. The location type is determined by its prefix.
# Unprefixed locations or locations starting with classpath: point to a package on the classpath and may contain both sql and java-based migrations.
# Locations starting with filesystem: point to a directory on the filesystem and may only contain sql migrations. 
# IdmFlywayMigrationStrategy resolves used jdbc database dynamically - ${dbName} in location could be used.
flyway.core.locations=classpath:eu/bcvsolutions/idm/core/sql/${dbName}

Module configuration

Information about module can be defined in property file (module-<module>.properties - e.g. module-core.properties). This property file is loaded by PropertyModuleDescriptor. Module properties are not editable through ConfigurationService (idm.pub. prefix is not used).

# mapping pom.xml properties by default
# add custom properties if needed
#
# module version
module.<module>.build.version=@project.version@
# build number
module.<module>.build.number=@buildNumber@
module.<module>.build.timestamp=@timestamp@
# module vendor
module.<module>.build.vendor=@project.organization.name@
module.<module>.build.vendorUrl=@project.organization.url@
module.<module>.build.vendorEmail=info@bcvsolutions.eu
# module description
module.<module>.build.name=@project.name@
module.<module>.build.description=@project.description@

Swagger

In the application profile (application.properties)

## Swagger config
# enable swagger endpoint (can be disabled for development etc.)
springfox.documentation.swagger.enabled=true
# endpoint with exposed documentations. Documentations are exposed by module e.g. <server>/api/doc?group=core
springfox.documentation.swagger.v2.path=/api/doc
#
# for static documentation generation puprose => internal usage mainly in test stage. Swagger specification on then rest endpoint is exported to given file e.g. <module>/target/swagger/swagger.json. Properties with @ are automatically filled from pom.xml properties.
# output directory and filename for swagger export - other build parts are dependent on this.
springfox.documentation.swagger.outputDir=@swagger.output.dir@
springfox.documentation.swagger.outputFilename=@swagger.output.filename@

Emailer

In the application profile (application.properties) - overloadable via ConfigurationService.

# enable test mode - in this mode, emails are not send
idm.sec.core.emailer.test.enabled=false
 # http://camel.apache.org/mail.html
idm.sec.core.emailer.protocol=smtps
idm.sec.core.emailer.host=smtp.gmail.com
idm.sec.core.emailer.port=465
idm.sec.core.emailer.username=servis.bcvsolutions@gmail.com
idm.sec.core.emailer.password=*****
# The FROM email address.
idm.sec.core.emailer.from=idm@bcvsolutions.eu

Templates

In the application profile (application.properties) - overloadable via ConfigurationService.

# Templates location
# more locations can be given e.g. classpath*:/eu/bcvsolutions/idm/template/,classpath*:/external/templates/
# resources in the latest location has the highest priority (last wins). Resources are prioritized - put resource, which has to override some core resource to last location
# Locations can be configured https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#resources
idm.sec.core.notification.template.folder=classpath*:/eu/bcvsolutions/idm/template/
idm.sec.core.notification.template.fileSuffix=**/**.xml # template suffix

Scripts

In the application profile (application.properties) - overloadable via ConfigurationService.

# Scripts location
# more locations can be given e.g. classpath*:/eu/bcvsolutions/idm/scripts/,classpath*:/external/scripts/
# resources in the latest location has the highest priority (last wins). Resources are prioritized - put resource, which has to override some core resource to last location
# Locations can be configured https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#resources
idm.sec.core.script.folder=classpath*:/eu/bcvsolutions/idm/scripts/
idm.sec.core.script.fileSuffix=**/**.xml

Scheduler

In the application profile (application.properties).

# Enable scheduler. Enabled by default
scheduler.enabled=true
# Task queue processing period (ms). Default 1000ms.
scheduler.task.queue.process=1000
# Application settings for QUARTZ (for current mvn profile)
scheduler.properties.location=/quartz.properties
# Task executor core pool size. Uses CPU count as default.
scheduler.task.executor.corePoolSize=
# Task executor max pool size. Uses CPU corePoolSize * 2 as default. 
# maxPoolSize has to be higher than corePoolSize (IllegalArgumentException is thrown otherwise).
# When queueCapacity is full, then new threads are created from corePoolSize to maxPoolSize.
scheduler.task.executor.maxPoolSize=
# Waiting tasks to be processed. Uses {@code Integer.MAX_VALUE} as default.
# {@link AbotrPolicy} is set for rejected tasks.	
scheduler.task.executor.queueCapacity=
# Thread priority for threads in event executor pool - 5 by default (normal).
scheduler.task.executor.threadPriority=
# Event queue processing period (ms). Default 1000ms.
scheduler.event.queue.process=1000
# Event executor core pool size. Uses CPU count * 2 as default.
scheduler.event.executor.corePoolSize=
# Event executor max pool size. Uses CPU corePoolSize * 2 as default. 
# maxPoolSize has to be higher than corePoolSize (IllegalArgumentException is thrown otherwise).
# When queueCapacity is full, then new threads are created from corePoolSize to maxPoolSize.
scheduler.event.executor.maxPoolSize=
# Waiting events to be processed. Uses corePoolSize * 2 as default.
# {@link AbotrPolicy} is set for rejected tasks.
scheduler.event.executor.queueCapacity=
# Thread priority for threads in event executor pool - 6 by default (a little higher priority than normal 5).
scheduler.event.executor.threadPriority=

Identity

In the application profile (application.properties) - overloadable via ConfigurationService.

# supports delete identity. Needed on FE (=> public) to render available bulk action in table 
idm.pub.core.identity.delete=true
#
# default password change type for custom users, one of values: 
# DISABLED - password change is disable
# ALL_ONLY - users can change passwords only for all accounts
# CUSTOM - users can choose for which accounts change password
# Needed on FE (=> public) 
idm.pub.core.identity.passwordChange=ALL_ONLY
#
# required old password for change password. Needed on FE (=> public) 
idm.pub.core.identity.passwordChange.requireOldPassword=true
#
# create default identity's contract, when identity is created.
# skipped in synchronizations - contract synchronization should be provided.
idm.pub.core.identity.create.defaultContract.enabled=true
#
# supports authorization policies for extended form definitions and their values for identities
# Default is false (backward compatibility) - all form definitions and attributes will be shown (controlled by permissions for identity - IDENTITY_READ / IDENTITY_UPDATE).
# true - authorization policies will be evaluated (see https://wiki.czechidm.com/devel/documentation/security/dev/authorization#secure_identity_form_extended_attribute_values) for form definitions (FORMDEFINITION_AUTOCOMPLETE is needed to show form definition) and for form values (FORMVALUE_UPDATE) 
idm.sec.core.identity.formAttributes.secured=false

Identity contract slice

In the application profile (application.properties) - overloadable via ConfigurationService.

# The protected interval can be set using the property idm.sec.core.contract-slice.protection-interval, where the value is the number of days.
# If the number of days between the termination of the contract and its renewal in the following time slice is less than or equal to the number
# of days set in the protection interval, then the date of the contract validity from the following slice will be used instead of the date of 
# termination of the contract from the currently valid slice.
idm.sec.core.contract-slice.protection-interval=0

Role

In the application profile (application.properties) - overloadable via ConfigurationService.

# Default user role will be added automatically, after an identity is logged in
# could contains default authorities and authority policies configuration
# for adding autocomplete or all record read permission etc.
idm.sec.core.role.default=userRole
# Admin user role
idm.sec.core.role.admin=superAdminRole

Tree

Tree structures configuration properties.

In the application profile (application.properties) - overloadable via ConfigurationService.

# Default tree type (uuid or code). More in Default organizational structure doc.
idm.sec.core.tree.defaultType=
# Default tree node (uuid) - is used, when default contract is created. More in Contractual relationship doc.
idm.sec.core.tree.defaultNode=

Internal properties used for tree indexing (forest index) - holds index state:

# forest index is valid. Is set to false, when index exception occurs and tree index has to be rebuild 
idm.sec.core.treeType.<tree-code>.valid=true
# rebuild index in progress (true). When tree type index rebuild is in progress, then tree node cannot be created / updated / deleted.
idm.sec.core.treeType.<tree-code>.rebuild=false

Entity events

In the application profile (application.properties) - overloadable via ConfigurationService.

# disable / enable asynchronous event processing. Events will be executed synchronously, if it's disabled. Enabled by default.
idm.sec.core.event.asynchronous.enabled=true
# Asynchronous events will be executed on server instance with id. Default is the same as {@link ConfigurationService#getInstanceId()} (current server instance).
idm.sec.core.event.asynchronous.instanceId=

Entity event processors

In the application profile (application.properties) - overloadable via ConfigurationService. Every processor could have his own configuration properties under prefix:

# disable / enable event procesor
idm.sec.<module>.processor.<name>.enabled=true
# override event types for given processor
idm.sec.<module>.processor.<name>.eventTypes=CREATE,UPDATE

Where <module> is processor's module a <name> is processor's name (see overridable processor's methods). Filled configuration properties will be shown on processor's content.

Common configuration properties for all processors:

Exists processors configuration: implemented proccessors.

Notification from Workflow

## Global property that allow disable or enable sending notification from WF
idm.sec.core.wf.notification.send=false
## Enable sending notification of changing roles to user, whose account will be modified
idm.sec.core.wf.notification.applicant.enabled=false
## Enable sending notification of changing roles to user, who made request
idm.sec.core.wf.notification.implementer.enabled=true

Confidential storage

Properties is not overloadable via ConfigurationService. For more info see

# Cipher secret key for crypt values in confidential storage
# for crypt values is used secretKey - secret.key
# Can be empty => confidential storage will not be crypted, application cannot be used in production (dev, test only).
cipher.crypt.secret.key=
# or secretKey defined in the external file - secret.keyPath
# cipher.crypt.secret.keyPath=/path/to/key

Entity filters

In the application profile (application.properties) - overloadable via ConfigurationService. Every filter could have his own configuration properties under prefix:

# enable/ disable filter - enabled by default. When filter is disabled and property is filled in filter, then ''disjunction'' criteria is added => no data will be returned
idm.sec.<module>.filter.<entity>.<name>.enabled=true
# filter implementation
idm.sec.<module>.filter.<entity>.<name>.impl=<beanName>

Where:

Common configuration properties for all filters:

Exists filters configuration: implemented filters.

Notification senders

In the application profile (application.properties) - overloadable via ConfigurationService. Senders could have his own configuration properties under prefix:

# sender implementation
idm.sec.<module>.notification-sender.<notificationType>.impl=<beanName>

Where:

Common configuration properties for all senders:

Read more about notification manager.

Authentication

UUID of system, against which to user will be authenticated.

# ID system against which to authenticate
idm.sec.security.auth.systemId=

Authentication filters

In the application profile (application.properties) - overloadable via ConfigurationService. Authentication filter could have his own configuration properties under prefix:

# enable/ disable filter - enabled by default or by filter implementation.
idm.sec.<module>.authentication-filter.<name>.enabled=true

Where:

Common configuration properties for all filters:

SSO authentication filter

Single-Sign-On mechanism can be configured with following properties:

# Allow SSO authentication
idm.sec.core.authentication-filter.core-sso-authentication-filter.enabled=false
# The name of the header which contains the login of the authenticated user
idm.sec.core.authentication-filter.core-sso-authentication-filter.header-name=REMOTE_USER
# The suffixes to remove from the login - usually domains
idm.sec.core.authentication-filter.core-sso-authentication-filter.uid-suffixes=
# The uids that can't be authenticated by SSO
idm.sec.core.authentication-filter.core-sso-authentication-filter.forbidden-uids=

Backup

If you want to use redeploy and backup for example in agenda (notification template), you must define default backup folder see:

# configuration property for default backup 
idm.sec.core.backups.default.folder.path=/tmp/backup

Http proxy

For outgoing http communication, you can set a proxy (currently used only by ReCaptcha).

Server restart is needed to apply this configuration change.

# Proxy for HTTP requests
idm.sec.core.http.proxy=12.34.56.78:1234

CGLIB

CGLIB for creating proxies has to be enforced. Is possible to use annotations on methods, which is not defined in service interface. Prevent to use some logic in service constructors (will be called twice) and always define annotations in implementation class, read more.

# use cglib for proxies by default
spring.aop.proxy-target-class=true

Virtual system

VS configurations allows define implementers via assigned IdM role or directly by selected identities. If you do not define none directly implementers and none role in VS configuration, then will be used implementers from default role. Default role can be defined in configuration:

# If you do not define default role, then will be used **superAdminRole** as default!
idm.sec.vs.role.default=<some-code-of-role>

Provisioning

# It's possible to send additional attributes, when password is changed (mapped attributes with flag sendOnPasswordChange)
# - true: additional password attributes will be send in one provisioning operation together with password
# - false: additional password attributes will be send in new provisioning operation, after password change operation
idm.sec.acc.provisioning.sendPasswordAttributesTogether=true
 
# It's possible to automatic mapped existed account on the target system. It means, before create new account (call create on the connector),
# we try to found account (by generated UID) on the target system. If account will be 
# returned, then will be mapped on the IdM account. Target account will be reused and only updated by connector.
# - true: for reusing account
# - false: for not reusing account
# - Default value is 'true'
idm.sec.acc.provisioning.allowedAutoMappingOnExistingAccount=true

Reports

Report executor

In the application profile (application.properties) - overloadable via ConfigurationService. Every report executor (~report) could have his own configuration properties under prefix:

# disable / enable report
idm.sec.<module>.report-executor.<name>.enabled=true

Where <module> is report's module a <name> is report's name.

Common configuration properties for all reports:

Report renderer

In the application profile (application.properties) - overloadable via ConfigurationService. Every report renderer could have his own configuration properties under prefix:

# disable / enable renderer
idm.sec.<module>.report-renderer.<name>.enabled=true

Where <module> is renderer's module a <name> is renderer's name.

Common configuration properties for all renderers: