====== Groovy scripts and their authorization ====== ===== Process of executing a script ===== While a script is executed, each used class in the script body is checked. Every class must be allowed in the allowed classes or services. The check is made by the [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/security/domain/GroovySandboxFilter.java|GroovySandboxFilter]] in the method [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/security/domain/GroovySandboxFilter.java#L77-L100|filter]]. In this method is resolved [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/security/domain/GroovySandboxFilter.java#L82-L89|class wrapped as proxy]] to simple classes. This control prevents undesirable use of classes. ===== Script authorization ===== It's possible to add authorities for the script after it's created. The authorities consist of classes and services, which can be used in the script. **These authorities are only for the script that owns these authorities**. Scripts don't share authorities between each other. {{ :devel:documentation:transformation_scripts:dev:script-authorities.png?nolink |}} Permissions for each script are of two basic types: * Services - beans/services which implement interface [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-api/src/main/java/eu/bcvsolutions/idm/core/api/script/ScriptEnabled.java|ScriptEnabled]]. An instance of this service is put into the script and the script is able to call public methods of this service. Before the script definition is saved, it's checked [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/model/service/impl/DefaultIdmScriptAuthorityService.java#L68-L80|if the service exists in allowed classes.]] * Classes - All available classes in java. Before the script definition is saved, it's checked [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/model/service/impl/DefaultIdmScriptAuthorityService.java#L58-L66| if the class exists.]] === Allowed classes === The following classes don't need to be specially added as script authorities (they are allowed by default) - [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/security/domain/GroovySandboxFilter.java#L41-L46|GroovySandboxFilter]] String.class, Integer.class, Double.class, Long.class, Date.class, Enum.class, Boolean.class, BigDecimal.class, UUID.class, Character.class, GuardedString.class, DateTimeFormatter.class, DateTimeFormat.class, DateTime.class, String[].class, LocalDateTime.class, Map.class, HashMap.class, List.class, ArrayList.class, Set.class, HashSet.class, LoggerFactory.class, Logger.class, ch.qos.logback.classic.Logger.class ===== Evaluating a script from another script ===== Scripts call other scripts via **scriptEvaluator** (scriptEvaluator is automatically added into its parent script - for example transformation to, and with builder is sent to child scripts). The instance of scriptEvaluator must be named as **scriptEvaluator**. **Example of calling another script with code 'test':** def result = scriptEvaluator.evaluate( scriptEvaluator.newBuilder() .setScriptCode('test') .addParameter('scriptEvaluator', scriptEvaluator) .addParameter('text', 'this is example text') .build()); We've called the **test** script. The script has as parameters scriptEvaluator (script can call another script - CAUTION though, scripts can call only scripts from the same category, or from a BASIC category). The next parameter is called **text**, the attribute text contains some sample text. The result from the evaluated script with code **test** will be in the **result** attribute. The parent script must have authorities for classes that the child scripts returns. Caution: authorities used in the script **aren't** shared with the child or parent script. Currently, there is no control loop script between the pair. // a sample loop script in between the pair, script A (code: parent) and script B (code: child) // script A (code: parent) scriptEvaluator.evaluate( scriptEvaluator.newBuilder() .setScriptCode('child') .build()); // script B (code: child) scriptEvaluator.evaluate( scriptEvaluator.newBuilder() .setScriptCode('parent') .build()); // script A calls script B - an infinity loop Be careful: if there is no return statement at the end, the script will return the last initialized attribute. ==== IdmSecurityException ==== If you use classes that are not among the allowed authorities, an exception [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/security/exception/IdmSecurityException.java|IdmSecurityException]] is thrown. The exception is caught in [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/script/evaluator/AbstractScriptEvaluator.java#L101-L109|AbstractScriptEvaluator]]. The exception contains code, name and category of the script that has thrown the exception. The logged exception is currently only for scripts evaluated by means of a scriptEvaluator. ==== scriptEvaluator and Builder ==== A script inside another script can be called with the **scriptEvaluator** instance. **scriptEvaluator** is the child of class [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/script/evaluator/AbstractScriptEvaluator.java|AbstractScriptEvaluator]]. Children are classified by [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/frontend/czechidm-core/src/enums/ScriptCategoryEnum.js|ScriptCategoryEnum]]. **It is only permitted to call scripts within the same category or basic category.** As a parameter [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/script/evaluator/AbstractScriptEvaluator.java#L128-L130|metody evaluate]] in scriptEvaluator you add **[[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/script/evaluator/AbstractScriptEvaluator.java#L143-L181|Builder]]**. The only required parameter is the **code** of the script. scriptEvaluator.evaluate( scriptEvaluator.newBuilder() .setScriptCode('SCRIPT_CODE_001') .addParameter('scriptEvaluator', scriptEvaluator) .addParameter('attributeValue', attributeValue) .addParameter('entity', entity) .addParameter('text', 'test') .build()); === DefaultTransformToResourceEvaluator === [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/acc/src/main/java/eu/bcvsolutions/idm/acc/script/evaluator/DefaultTransformToResourceEvaluator.java|DefaultTransformToResourceEvaluator]] - evaluator for transformation to a system, can call a script from the TRANSFORM_TO or DEFAULT categories. The evaluator is automatically added into the transformation to a system. === DefaultTransformFromResourceEvaluator === [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/acc/src/main/java/eu/bcvsolutions/idm/acc/script/evaluator/DefaultTransformFromResourceEvaluator.java|DefaultTransformFromResourceEvaluator]] - evaluator for transformation from a system, can call a script from the TRANSFORM_FROM or DEFAULT categories. The evaluator is automatically added into the transformation from a system. === DefaultScriptEvaluator === [[https://github.com/bcvsolutions/CzechIdMng/blob/develop/Realization/backend/core/core-impl/src/main/java/eu/bcvsolutions/idm/core/script/evaluator/DefaultScriptEvaluator.java|DefaultScriptEvaluator]] - Evaluator for the DEFAULT category. The default script can be called from other scripts. ===== Attribute mapping and scripts ===== Code for script calling can be generated by a frontend component script area (see the first picture and button insert script). Modal window (second picture) is a list of all available scripts. {{ :devel:documentation:transformation_scripts:dev:script-transformation-02.png?nolink |}} {{ :devel:documentation:transformation_scripts:dev:script-transformation-01.png?nolink |}} ===== Script debug ===== For each script, a logger is enabled. Example of some messages: org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger("script_name"); LOG.info("INFO Log"); LOG.error("ERROR Log"); LOG.warn("WARN Log"); If you want to see debug messages, you must initialize a LOG with prefix **eu.bcvsolutions.idm.**. Or update logback-spring.xml. org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger("eu.bcvsolutions.idm.script_name"); LOG.debug("DEBUG Log"); ==== Direct log only to console ==== To print a message to log, you can use the classic //System.out.println// statement, or better print: println("test") The second one doesn't need additional authorities. ===== Script upload and backup ===== ==== Backup ==== Scripts agenda provides a backup of all scripts that are loaded in the CzechIdM. First, you must define a path to store the backup files. The path is defined by the application property: **idm.sec.core.backups.default.folder.path**. The backup folder must have permissions for read+write+execute, for the user that runs the application server (e.g. tomcat). Every script will be saved into this folder with this name: \_\_.xml ==== Redeploy ==== The script agenda also provides functionality for the redeploy of **existing** scripts. Only the existing new script is deployed to IdM on application restart. For redeploy you can use backup files. CzechIdM loads all files in a defined folder with a defined suffix (idm.sec.core.script.folder and idm.sec.core.script.fileSuffix). **The file name does not matter.** Script is loaded by code defined inside xml. Redeploy folder is defined by the property: **idm.sec.core.script.folder**. The property can contain the class path or folder. A sample folder: ''%%file:///opt/czechidm/backup/%%'', a sample class path: '' classpath*:/eu/bcvsolutions/idm/scripts/'' If you use a file folder, CzechIdM must have read+write+execute permissions on the folder that contains scripts as well as read permission on files. ===== Available services in script ===== For list of basic usable services in all scripts please visit [[devel:documentation:transformation_scripts:dev:available_services|this page]]. ===== FAQ ===== [[faq:scripts:start|Scripts FAQ]]