Skip to content

DmitryKubahov/sail-point-improved

Repository files navigation

SailPoint improved

Description

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.

Structure

Modules:

  1. sail-point-annotation-parent - group of modules contains annotations and processors for generating xml sources from java classes

    1. sail-point-annotation - all external annotations, as for generating xml and as for other modules

    2. sail-point-annotation-processor - annotation processors for generating xml from java classes. Current implementation supported generating:

      • ✓ Rules

      • ✓ Custom objects

    3. sail-point-improved - extends standard IdentityIQ classes for improvements (e.g. JavaRuleRunner)

    4. sail-point-customization - shows how to use all this stuff.

Build

For start using it:

  1. Add 2 IdentityIQ dependencies to local maven repository. Script for adding jars is located in /bin directory. List of custom jars:

    1. identityiq.jar

    2. 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

Improvements

All current improvements for IdentityIQ are in this block.

Rule

All rules can be separated into 2 groups: with output and none.

JavaRulesInheritance

Example

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:

  1. No need to write code in xml

  2. Debugging rules (no beanshell)

  3. Performance improvements (~10 times faster than beanshell)

  4. Tests (mockito, jmockit…​)

  5. No need to copy-paste from java class code to xml and vice versa

Custom object

There are 2 main parts of custom object:

  1. Name - the unique value

  2. Attributes - properties for object. To get properties value developers usually use one of it function: get(), getInt(), getList(), etc.

Implementation

There is AbstractCustomObject class which contains all necessary methods to work with custom object:

AbstractCustomObject

Factory

To simplify working with instance life-cycle of custom object work with CustomObjectFactory class:

CustomObjectFactory

Example

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:

  1. Auto-generation xmls

  2. Working with a custom object as a simple java class

  3. Customization of loading/saving properties to custom object

  4. Creating/modifying custom object in run-time using a certain java class

  5. Testing

Dockerization

Sources: /bin/docker
Documentation: README.adoc

About

Project for improved SailPoint features

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages