Current project contains modules to improve SailPoint IdentityIQ projects. The main aims of the projects: simplify some areas in IdentityIQ, increasing performance, doing IdentityIQ developers life easier.
Modules:
-
sail-point-annotation-parent - group of modules contains annotations and processors for generating xml sources from java classes
-
sail-point-annotation - all external annotations, as for generating xml and as for other modules
-
sail-point-annotation-processor - annotation processors for generating xml from java classes. Current implementation supported generating:
-
✓ Rules
-
✓ Custom objects
-
-
sail-point-improved - extends standard IdentityIQ classes for improvements (e.g. JavaRuleRunner)
-
sail-point-customization - shows how to use all this stuff.
-
For start using it:
-
Add 2 IdentityIQ dependencies to local maven repository. Script for adding jars is located in /bin directory. List of custom jars:
-
identityiq.jar
-
connector-bundle.jar
-
Important
|
All versions in main pom for dependencies were taken from lib directory of identityiq,war. They all quite old and one (lucene) with vulnerable. |
Build command:
mnv clean install
All current improvements for IdentityIQ are in this block.
All rules can be separated into 2 groups: with output and none.
Simple JDBCBuildMap rule type implementation. According to documentation JDBCBuildMap has input attributes and output: map of names/values.
Name of new rule: SimpleJDBCBuildMapRule. Functionality: check value from column: active_status and if value is 'T', than put true, else false (very simple rule). Code:
/**
* Simple implementation of {@link JDBCBuildMapRule} rule
*/
@Slf4j
@Rule(value = "Simple JDBC build map rule", type = sailpoint.object.Rule.Type.JDBCBuildMap)
public class SimpleJDBCBuildMapRule extends JDBCBuildMapRule {
/**
* Active status attribute name
*/
static final String ATTR_ACTIVE_STATUS_NAME = "active_status";
/**
* Active status true value
*/
static final String TRUE_ACTIVE_STATUS_VALUE = "T";
/**
* Check default string attribute {@link SimpleJDBCBuildMapRule#ATTR_ACTIVE_STATUS_NAME} and replace it with boolean value:
* Y - true
* all other values - false
*/
@Override
@Argument(name = "map", type = ArgumentType.RETURNS, isReturnsType = true)
protected Map<String, Object> internalExecute(JavaRuleContext context,
JDBCBuildMapRuleArguments arguments) throws GeneralException {
try {
log.debug("Try to get default map");
Map<String, Object> map = JDBCConnector.buildMapFromResultSet(arguments.getResult());
log.debug("Check:[{}] attribute in default map", ATTR_ACTIVE_STATUS_NAME);
log.trace("Default map:[{}]", map);
String activeStatus = (String) map.get(ATTR_ACTIVE_STATUS_NAME);
log.trace("[{}] attribute value in default map:[{}]", ATTR_ACTIVE_STATUS_NAME, activeStatus);
map.put(ATTR_ACTIVE_STATUS_NAME, TRUE_ACTIVE_STATUS_VALUE.equalsIgnoreCase(activeStatus));
return map;
} catch (Exception ex) {
log.error("Got error:[{}] while executing rule", ex.getMessage(), ex);
throw new GeneralException(ex);
}
}
}
Result generated XML:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="java" name="Simple JDBC build map rule" type="JDBCBuildMap">
<Description>Simple implementation of {@link JDBCBuildMapRule} rule</Description>
<Signature returnType="java.util.Map">
<Inputs>
<Argument name="application" type="sailpoint.object.Application">
<Description>A reference to the Application object</Description>
</Argument>
<Argument name="schema" type="sailpoint.object.Schema">
<Description>A reference to the Schema object for the JDBC source being read</Description>
</Argument>
<Argument name="state" type="java.util.Map">
<Description>A Map that can be used to store and share data between executions of this rule during a single aggregation run</Description>
</Argument>
<Argument name="result" type="java.sql.ResultSet">
<Description>The current ResultSet from the JDBC connector</Description>
</Argument>
<Argument name="connection" type="java.sql.Connection">
<Description>A reference to the current SQL connection</Description>
</Argument>
</Inputs>
<Returns>
<Argument name="map" type="java.util.Map">
<Description>Check default string attribute {@link SimpleJDBCBuildMapRule#ATTR_ACTIVE_STATUS_NAME} and replace it with boolean value:
Y - true
all other values - false</Description>
</Argument>
</Returns>
</Signature>
<Source>com.sailpoint.rule.connector.SimpleJDBCBuildMapRule</Source>
</Rule>
Advantages of using java classes as source of rules:
-
No need to write code in xml
-
Debugging rules (no beanshell)
-
Performance improvements (~10 times faster than beanshell)
-
Tests (mockito, jmockit…)
-
No need to copy-paste from java class code to xml and vice versa
There are 2 main parts of custom object:
-
Name - the unique value
-
Attributes - properties for object. To get properties value developers usually use one of it function: get(), getInt(), getList(), etc.
There is AbstractCustomObject class which contains all necessary methods to work with custom object:
To simplify working with instance life-cycle of custom object work with CustomObjectFactory class:
Simple custom object class source:
/**
* Simple test custom object example class
*/
@Data
@Custom("Simple custom object")
public class SimpleCustomObject extends AbstractCustomObject {
/**
* Test string value
*/
@Attribute(@AttributeValue("single"))
private String stringValue;
/**
* Test string value as collection
*/
@Attribute(@AttributeValue("stringCollection"))
private List<String> stringCollection;
/**
* Test strings values
*/
@Attribute({
@AttributeValue("string1"),
@AttributeValue("string2")
})
private List<String> stringsCollectionNatural;
/**
* Test boolean value
*/
@Attribute(@AttributeValue("true"))
private Boolean booleanValue;
/**
* Test long value
*/
@Attribute(@AttributeValue("5"))
private Long longValue;
/**
* Test date value
*/
@Attribute(@AttributeValue("02/15/2019 10:35:45"))
private Date dateValue;
/**
* Test date map
*/
@Attribute({
@AttributeValue(key = "now", value = "now"),
@AttributeValue(key = "02/15/2019 10:35:45", value = "02/15/2019 10:35:45")
})
private Map<String, Date> dateMap;
/**
* Test boolean map
*/
@Attribute({
@AttributeValue(key = "false", value = "false"),
@AttributeValue(key = "true", value = "true")
})
private Map<String, Boolean> booleanMap;
/**
* Test set of string
*/
@Attribute({
@AttributeValue(value = "1"),
@AttributeValue(value = "2"),
@AttributeValue(value = "1")
})
private Set<String> setValue;
/**
* Test attribute name
*/
@Attribute(name = "attributeName", value = @AttributeValue("nameTest"))
private String fieldName;
/**
* Test transient attribute name
*/
private String transientField;
}
Generated XML:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Custom PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Custom name="Simple custom object">
<Attributes>
<Map>
<entry key="attributeName" value="nameTest"/>
<entry key="booleanMap">
<value>
<Map>
<entry key="false">
<value>
<Boolean></Boolean>
</value>
</entry>
<entry key="true">
<value>
<Boolean>true</Boolean>
</value>
</entry>
</Map>
</value>
</entry>
<entry key="booleanValue">
<value>
<Boolean>true</Boolean>
</value>
</entry>
<entry key="dateMap">
<value>
<Map>
<entry key="02/15/2019 10:35:45">
<value>
<Date>1550223345000</Date>
</value>
</entry>
<entry key="now">
<value>
<Date>1564403046656</Date>
</value>
</entry>
</Map>
</value>
</entry>
<entry key="dateValue">
<value>
<Date>1550223345000</Date>
</value>
</entry>
<entry key="longValue">
<value>
<Long>5</Long>
</value>
</entry>
<entry key="setValue">
<value>
<Set>
<String>1</String>
<String>2</String>
</Set>
</value>
</entry>
<entry key="stringCollection">
<value>
<List>
<String>stringCollection</String>
</List>
</value>
</entry>
<entry key="stringValue" value="single"/>
<entry key="stringsCollectionNatural">
<value>
<List>
<String>string1</String>
<String>string2</String>
</List>
</value>
</entry>
</Map>
</Attributes>
<Description>Simple test custom object example class</Description>
</Custom>
Advantages of using java classes as source of custom objects:
-
Auto-generation xmls
-
Working with a custom object as a simple java class
-
Customization of loading/saving properties to custom object
-
Creating/modifying custom object in run-time using a certain java class
-
Testing
Sources: /bin/docker
Documentation: README.adoc