# SailPoint Custom Connectors Documentation > Custom Connectors Documentation # Documentation # Custom Connector Interface Overview SailPoint has introduced an updated User Interface (UI) for SailPoint custom connectors which can dynamically render different elements and attributes. This refactoring of the source configuration is easier to understand and read, helping administrators take better advantage of the updated UI. In this document, you will learn how to create a connector UI which uses the updated interface. The UI is composed of a set of forms that an administrator interfaces with to configure a source. It examines the look and feel of the updated UI to help you understand its various components. Then, using an example connector, it examines various elements and their attributes. Finally, the document explains how to modify type attributes as and when that's required. For additional information on creating custom connectors, you can also refer to this article: [Creating a custom connector using SailPoint's OpenConnector framework](). ## Layout of the Updated User Interface The visual layout has three sections. You can customize the attributes within each element for various requirements in your applications. This sample UI shows the three sections, which are described in more detail below. Sections 1 (Side Panel) and 2 (Documentation) are consistent in layout and function for all connectors. Section 3, the Form section, contains attributes that will vary from connector to connector. > [!NOTE] > > **Screenshot** > > [![Custom connector user interface layout]()]() ### 1 - Side Panel Section The side panel is a list of Menu pages which allow you to navigate through the configuration. Each Menu page has its own Menu element comprising a Form Section and a Documentation Section. ### 2 - Documentation Section The documentation section is where you provide all the necessary information such as what values are expected or links to more references the admin requires during filling the form fields. ### 3 - Form Section The form section is a UI fill-in form for capturing the administrative input for the backend process. ## Prerequisites Familiarity with the source configuration development process is a prerequisite for implementing a connector using the updated UI. ## Setting Up a New UI Source Configuration Create a new UI source configuration in the elements such as fields, sections, and more. The following topics are covered in this section: - [Understanding an Example of a UI Source-Config](<#understanding-an-example-of-a-ui-source-config>) - [The Form Element](<#the-form-element>) - [To Upload the Files](<#to-upload-the-files>) - [The Menu Element](<#the-menu-element>) - [The Section Element](<#the-section-element>) - [The Field Element](<#the-field-element>) - [Using Attributes to Customize the Field Element](<#using-attributes-to-customize-the-field-element>) - [Using Type Attributes for Various Field Requirements](<#using-type-attributes-for-various-field-requirements>) - [placeHolder String Guidelines](<#placeholder-string-guidelines>) - [`parentKey` & `parentValue` Attribute Guidelines](<#parentkey-parentvalue-attribute-guidelines>) ### Understanding an Example of a UI Source-Config The following is an example of the ServiceNow UI source-config: ```xml
``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![ServiceNow user interface source configuration example]()]() > [!NOTE] > > The above UI representation of the Base Configuration Menu page is for reference only. You do not need to provide configuration details of Base Configuration in the source-config. For more information refer to the note under [The Menu Element](<#the-menu-element>) section. ### The Form Element The Form element is the root XML element that contains multiple Menu elements within it. It provides source config attribute information such as the XML namespace, connector type, status, etc. For example: ```xml
``` > [!NOTE] > > Be sure to use `sailpoint_form_2_0.xsd` to validate the structure and grammar of the source config. > > For example: > > ```xml > xmlns="http://www.sailpoint.com/xsd/sailpoint_form_2_0.xsd > ``` Definition of attributes in the Form element: - `xmlns` - Use `http://www.sailpoint.com/xsd/sailpoint_form_2_0.xsd` to ensure that the source config is validated correctly. - `name` - The name of the source that is shown in the drop-down list when you are creating a source. - `connectorName` - The type of the connector; this needs to be similar to the type attribute in the source config. - `type` - The connection type of the source. Its value is constant and is equal to SourceConfig. - `status` - Refers to the status of the source config. Its value is constant and is set as released. - `shortDesc` - Refers to the short description about the connector appearing on the create connector page. ### To Upload the Files This is a mandatory section for the custom connector. Add the BaseConfig element after the Form element to upload a custom connector jar file for the connector. For example: ```xml ``` Definition of attributes in the BaseConfig element: - `name` - The name of the file upload button. - `maxFiles` - The maximum number of files that can be uploaded. - `supportedExtensions` - The file extensions which are allowed to be uploaded. - `type` - The type of file component. - `maxSize` - The maximum file size allowed in MB. - `validateJSON` - If set to `true`, then the JSON file will be validated when it is uploaded. The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Base configuration file upload]()]() ### The Menu Element Each Menu item refers to an independent and navigable page containing different parameters of configuration. Different parameters are defined using the Section element(s). All the Menu elements together define the entire source configuration UI. > [!NOTE] > > A Menu element must be placed under the root element only, i.e. the Form element. You can include one or more Menu elements per your requirements. You need to provide all the Menu list items through the source-config, except for the **Base Configuration** and **Review and Test** items. **Base Configuration** parameters are common across all the connectors and are generated dynamically by the new framework and hence need not be provided through the source-config. The **Review and Test** Menu item aggregates and displays information from all the other Menu items, to review before testing the connection to the native system. This item is generated by the new framework dynamically, depending upon the configured source. Therefore, this also does not need to be provided through the source-config. For example: ```xml . . . . . . ``` Definition of attributes in the Menu element: - `name` - The name of a Menu item or a key for a corresponding localized message. The value of this attribute can also be used to form the URL that gets displayed in the browser's address bar when this Menu item is selected. - `label` - The label of a Menu item or a key for a corresponding localized message that should be displayed on the UI. The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Menu element]()]() ### The Section Element A Section is used to group a set of related form Field(s) such as textbox, drop-down list, etc. A section can include one or more Field elements. For example: ```xml
``` Definition of attributes in the Section element: - `name` - The Section(s) name or a key for a corresponding localized message of the Section. - `label` - The Section(s) label or a key for a corresponding localized message that should be displayed on the UI. - `sectionInfo` - The summary of the connector on the source list page. The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Section element]()]() ### The Field Element Fields represent different types of UI components depending on the attribute type value. There can be one or more Field elements within a Section. For example: ```xml ``` Definition of attributes in the Field element: - `name` - The name of the field or a key for the corresponding localized message. - `displayName` - The label of the field or a key for the corresponding localized message that should be displayed on the UI. - `placeHolder` - The additional placeholder information for the text field. The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Field element]()]() #### Using Attributes to Customize the Field Element These attributes can be used to customize the Field element, as required by the connector. ##### name The `name` attribute is used to reference the element in the form data after the form is submitted. The value of the name must be the same as that of the source/connector's configuration name. > [!IMPORTANT] > > If it is not added correctly, the source functionality may break. For example: ```xml ``` ##### displayName The `displayName` refers to the name of the fields in the form section. For example: ```xml ``` ##### helpkey The `helpkey` attribute refers to the help message for any complex field. If it is provided, then placeholder text is not needed, and vice versa. For example: ```xml ``` ##### placeholder The `placeholder` attribute refers to the placeholder information for the text field. This information vanishes as soon as the user enters something into the field. For example: ```xml ``` #### Using Type Attributes for Various Field Requirements ##### `type="text"` Represents a text box to read the string inputs. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Text box element]()]() > [!NOTE] > > The default max length for the text/URL/email field is 256 characters. If the input is more than 256 characters, be sure to specify the `maxlength` explicitly. > > For example: > > ```xml > > ``` ##### `type="secret"` Represents a text box to read secret string inputs like passwords, access keys, etc. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Secret text element]()]() ##### `type="textarea"` Represents an input field for reading long string inputs like descriptions, personalized feedback, etc. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Text area element]()]() ##### `type="number"` Represents a text box to read number inputs. The `min` and `max` attributes indicate the minimum and maximum values that can be entered. The `step` attribute indicates the factor by which we can increment/decrement the value using the "up/down" arrow buttons. For example, `step="2"` will allow us to increment/decrement the number by 2 (i.e. 2, 4, 6...) when the `min` value is set as 0. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Number element]()]() ##### `type="select"` Represents a drop-down list for selecting a single value. For example: ```xml ``` > [!NOTE] > > The options for a select field are configured as a static list. For example, if a user configures `field1` of `Menu 1` to save a list/array of cities. A select field named `field2` on `Menu 2` depends on the saved data of `field1` from `Menu 1` to populate its options. The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Select element]()]() ##### `type="radio"` Represents a radio button for choosing one option from a given set of options. For example: ```xml ``` > [!NOTE] > > The options for a radio field are configured as a static list. The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Radio button element]()]() ##### `type="typeahead"` Represents a type ahead field for choosing one option from a given set of options. The type ahead field type should be used when there are a lot of options and you want to make it easy for the end-users to search for the desired option from the list. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Type-ahead element]()]() > [!NOTE] > > The options for a `typeahead` field are configured as a static list. ##### `type="toggle"` Represents a button for selecting a Boolean value. > [!NOTE] > > The toggle field type should be used when it has other dependent fields to show/hide. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Toggle element]()]() ##### `type="checkbox"` Represents a field type for selecting a Boolean value. > [!NOTE] > > This type should be used only for independent fields. ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Checkbox element]()]() ##### `type="email"` Represents a field type for email details in XML format. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Email element]()]() > [!NOTE] > > The default max length for text/URL/email field is 256 characters. If more than 256 characters are required, be sure to specify a `maxlength` explicitly. > > For example: > > ```xml > > ``` ##### `type="url"` Represents a field type for URL details in XML format. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![URL element]()]() > [!NOTE] > > The default max length for text/URL/email field is 256 characters. If more than 256 characters are required, be sure to specify a `maxlength` explicitly. > > For example: > > ```xml > > ``` ##### `type="secrettextarea"` Represents the field type for secret text area details in XML format. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![Secret text area element]()]() ##### `type="list"` Represents the field type for list details in XML format. For example: ```xml ``` The following screenshot shows how the example is represented in the UI: > [!NOTE] > > **Screenshot** > > [![List element]()]() The source XML representation for the list component in the example above is: ```xml invalid 403 expired ``` ### placeHolder String Guidelines To escape quotes (`"`) in placeholder string, you can use `"`. For example, if the string is, "For example, filter for removing users with condition: deleted == "true" " You can write it as follows in XML: ```xml placeHolder="For example, filter for removing users with the condition: deleted == "true" " ``` ### `parentKey` & `parentValue` Attribute Guidelines The `parentKey` and `parentValue` attributes are used to specify a parent-child relationship between the two XML elements, where the element specifying them is considered the child. Use these as a Field element where `parentKey` specifies the name of the parent element and `parentValue` specifies the parent element's value. For example, suppose you want a Section (child) labeled "Connection Credentials" to be displayed on the UI only if another Field (parent) named `authtype` is set to `Basic`. Here is an example for this scenario: ```xml
... ...
``` Note that the child element has `parentKey="authtype"` where `authtype` is the name of the parent element and `parentValue="Basic"` where `Basic` is the parent element's value. The `parentKey`, `parentValue` attributes can be used with any type like select, toggle, radio, etc. to hide/show other Field and Section elements. # Implementing Custom Connectors This document describes how to create a custom connector using SailPoint's OpenConnector framework. SailPoint includes many connectors through which it can connect to external systems, both to read account and entitlement information and to process account provisioning requests. Occasionally, however, there may be a need to create a custom connector to connect to an application for which SailPoint does not have a built-in connector. Unless direct provisioning is required, custom connectors are seldom necessary because user data is generally available through files, database connections, etc. SailPoint's built-in connectors can consume data from delimited file extracts, database connections (JDBC), and web-services (REST), just to name a few. Even in cases where the data extract is not in a readily digestible format, there are configurations provided with these available connectors that can parse or otherwise pre-process the data to prepare it for recording in SailPoint; the developer writing the rules must, of course, be familiar with file parsing in Java. However, when provisioning is required or if these built-in features do not meet the business need, writing a custom connector using the open connector framework is a good option. > [!IMPORTANT] > > SailPoint strongly encourages both partners and customers alike to purchase SailPoint Expert Services hours to assist with custom connector creation. These deep level implementations are powerful, but also complex to create without proper experience. In addition, custom connectors are not covered by SailPoint Support. Any deployment of custom code is your own responsibility to create and maintain. > [!NOTE] > > Use the SailPoint SDK/CLI to develop connectors to SaaS systems. For more information, refer to [SaaS Connectivity](). ## Audience The audience of this document is the implementer who will develop, build, and test the connector, and then install it in SailPoint. SailPoint recommends that the implementer should be proficient in Java, comfortable working within the constraints of a software framework, and versed in the use of an IDE such as [Eclipse]() or [IntelliJ IDEA](). They must also know how to leverage [REST APIs](). SailPoint also highly recommends attending the [SailPoint Fundamentals of Identity Security Cloud Implementation]() training course. ## Feasibility While SailPoint has the ability to support custom connectors, analysis must be done to determine feasibility of integration with the target system. When SailPoint first evaluates which connectors to build, product engineers need to understand which supportable means can successfully integrate with a target system. So, the engineers need to understand what APIs the target system supports, as well as what is feasible to do via the REST API. You will need to coordinate with technical documentation and subject matter experts (SMEs) to evaluate the feasibility of integrating with a system. ## Connector Architecture In SailPoint, a source is a configured instance which communicates with an associated connector to read or write user account or entitlement objects. Connectors are technical component interfaces which communicate with target systems via native APIs to read or write user account or entitlement objects. Essentially, **sources** communicate with **connectors**. > [!NOTE] > > **Screenshot** > > [![Connector Architecture]()]() From a connector anatomical perspective, connectors are made up of three components: - The user interface displays a set of forms which an administrator completes to configure a source. - The source configuration is based on a configuration template. It contains all the information necessary to run the connector for the instance of that source. - The connector is the technical component(s) which take the configurations and apply them to the connector itself. The connector performs operations such as: - Account read or aggregation - Account creation, modification, or deletion - Provisioning activities So in SailPoint's environment, where can you find these artifacts? It is important to understand the architecture of how the various components interact with one another. In SailPoint, there are components which are stored in the cloud itself. However there is an on-premise cloud connector gateway which is deployed as part of the SailPoint-managed [Virtual Appliance](), or VA. The connectors run from the VA and communicate with the target system(s) which can be on your internal network, or in the cloud. > [!NOTE] > > **Screenshot** > > [![Virtual Appliance Architecture]()]() Based on the diagram, you can determine which components are deployed where, and how they should be configured. **User Interface Forms** - XML configuration - Deployed in the cloud **Source Configuration Template** - XML configuration - Deployed in the cloud **Custom Connector** - Compiled Java JAR package - Deployed in the SailPoint Virtual Appliance These will be used as a basis for the components which will be built in this guide. ## Designing Custom Connectors Once high level analysis of whether or not a connector can be built or not, you can start designing the various components. The following topics are covered in this section: - [Source Configuration Template](<#source-configuration-template>) - [Object Type and Schema](<#object-type-and-schema>) - [Choose Connector Features](<#choose-connector-features>) - [User Interface Forms](<#user-interface-forms>) - [Custom Connector Development](<#custom-connector-development>) ### Source Configuration Template The source configuration template is the default set of configurations for the source and the connector. In SailPoint, this defines three components: - **Default Connector Settings** - Configuration values used by the connector, such as host, port, user, and password. - **Default Schema** - Default user account attributes, as well as what makes an account unique. - **Default Correlation** - Default logic to match user accounts with owners. ```xml ... ... ``` The above example is an Application XML object. > [!IMPORTANT] > > "Application" is the internal name for a Source, not to be confused with Application SSO objects in SailPoint. The default configurations for the connector live in the Attributes section of the configuration. ### Object Type and Schema The account definition is in the schema section, specified with an `objectType="account"` attribute. While a connector can technically support multiple schemas, SailPoint currently only supports schemas with an `objectType` representing an account or group. The `identityAttribute` attribute specifies the Account ID, which is the attribute which makes an account unique. For example, `distinguishedName` is the Account ID for LDAP. The `displayAttribute` attribute specifies the Account Name, which is the attribute that an account is known by. Sometimes this can be set the same as the Account ID, but sometimes they differ. It depends on the object model from which you are reading. In the Application XML example above, these are set to the same attribute, called `Employee Number`. ### Choose Connector Features Determine the features for the connector. Available features are: - **AUTHENTICATE** - Enables the connector to support authenticating a user and password combination against the source - **CREATE** - Enables the connector to create a resource object. For example, can the connector create an account or group. - **DELETE** - Enables the connector to delete a given resource object by ID. - **DISCOVER\_SCHEMA** - Enables the connector to report schemas (account or group) to SailPoint when queried, including both attribute names and types. Valid types are BOOLEAN, DATE, INT, SECRET, STRING. - **ENABLE** - Enables the connector to enable or disable a resource object. - **GET** - Enables the connector to read and return a map of a specific resource object by ID. - **ITERATE** - Enables the connector to return an iterator of resource objects, such as filtered sets. - **PERMISSIONS** - Enables the connector to return permission attributes. - **SET\_PASSWORD** - Enables the connector to set the password of a resource object. - **UNLOCK** - Enables the connector to unlock a resource object. - **UPDATE** - Enables the connector to update resource objects. These features are listed as an enumeration in the `openconnector.connector` class, but this enumeration is not currently used to determine connector functionality; it is provided only as a connector design guide. The Application object also has a Feature enumeration, specified as the `FeaturesString` attribute in the application definition. This is used to control the functionality available through the connector. The Connector Feature enumeration overlaps with but is not identical to the Application Feature enumeration. They correlate as shown here: | Connector Features | Application Features | | --- | --- | | AUTHENTICATE | AUTHENTICATE | | CREATE | PROVISIONING | | DELETE | PROVISIONING | | DISCOVER\_SCHEMA | DISCOVER\_SCHEMA | | ENABLE | ENABLE and PROVISIONING together | | GET | Opposite of NO\_RANDOM\_ACCESS (this is an assumed function for all applications unless explicitly turned off) | | ITERATE | No specific feature, assumed functionality for all applications | | PERMISSIONS | DIRECT\_PERMISSIONS | | SET\_PASSWORD | PASSWORD and PROVISIONING together | | UNLOCK | UNLOCK and PROVISIONING together | | UPDATE | PROVISIONING | ### User Interface Forms Once you understand all the configurations, you can start designing the user interface forms. Create the user interface forms which you interact with and provide configurable elements which an administrator can use to configure a source. For example: > [!NOTE] > > **Screenshot** > > [![User Interface Forms]()]() The technical implementation of this is built as an XML form object, which is understood by SailPoint and renders configurable form elements, such as text fields, checkboxes, radio buttons, or select boxes. These also support default values (assuming your source configuration template doesn't define these), and you can even mark fields as required or hidden. You can leverage SailPoint's **Advanced** section to hide more complex configurations if you need to. For example: ```xml
OAuth PKI ... ... ``` ### Custom Connector Development Develop the technical implementation of the connector using the OpenConnector framework. The custom connector architecture uses the OpenConnector framework provided by SailPoint in the `openConnector` package. All custom connectors must inherit from `openconnector.AbstractConnector`, which implements the `openconnector.Connector` interface. The connectors are stateful and require configuration, use, and closure. > [!NOTE] > > The connector SDK, which includes the OpenConnector classes and the javadocs, is available for download [here](). Using the `openConnector` framework, developers must implement separate methods for different types of operations. These methods are automatically called by SailPoint interfaces in the cloud connector gateway in the VA. Popular methods of the OpenConnector framework are as follows: > [!NOTE] > > **Screenshot** > > [![OpenConnector Framework Methods]()]() The following is a chart which details these in greater detail. Methods marked with an asterisk (`*`) are required for any custom connector, regardless of the feature set chosen. However, the custom connector can simply defer to the AbstractConnector's default behavior instead of implementing its own version of the method when that method has been defined in the AbstractConnector class. AbstractConnector's provided functionality for each of these methods is noted below. In some cases, AbstractConnector provides some default functionality that can be used or overridden by the custom class. In other cases, it contains no method or contains a method that throws an unsupported operation exception, both of which require the method to be written in the custom connector class for the operation to be supported. | Method | Description | Default Behavior of AbstractConnector's Method | | --- | --- | --- | | `getSupportedObjectTypes()` `*` | Should return a list of the connector's supported object types. | Returns Account | | `getSupportedFeatures()` | Should return the list of supported features for the connector

Note - This method is not currently used by SailPoint. Instead, the application object's FeaturesString is used to determine the connector's supported features. | Returns GET and ITERATE | | `configure()` `*` | Should set up any configuration information which might be helpful in supporting other connector functionality; this is called only once during connector construction

Note - The default behavior is helpful since it makes the connector's attributes available to other methods, so if this method is implemented in the custom connector class, it should call its super method as well. | Saves the connector config and log objects passed to it in local variables for later use by other methods. | | `setObjectType()` `*` | Sets the object type, which can influence the read, iterate, and provision behaviors of the connector when the methods supporting those functions contain separate functionality for each object type; is called by the OpenConnectorAdapter to set the correct target object type before executing operations. | Sets the object type to the type named in the method call (defaulting to "account" if none are named) and retrieves the schema for that type from the connector configuration. | | `close()` | Should perform any required steps to close the connection to the application. | Does nothing | | `testConnection()` `*` | Should determine if the resource is accessible; e.g. connect to the application with login credentials pulled from the connector configuration. | Throws unsupported | | `discoverSchema()` | Should return the schema (attributes and data types) of the currently selected object type. | Throws unsupported | | `authenticate()` | Should connect to the application with the credentials provided in the method call and attempt to authenticate to the application with that user id and password. | Throws unsupported | | `read()` | Should refresh the account or group in SailPoint corresponding to the provided native identity to match its current values in the application (i.e. targeted aggregation functionality). This can also be used in preparation for an update operation to ensure SailPoint has the latest data from the application before performing any updates. | Not implemented | | `iterate()` | Should return an iterator over the accounts/groups in the application (can be a subset of accounts/groups based on a specified filter). | Not implemented | | `provision()` | Should parse the provisioningPlan and drive provisioning activities.

Note - Most custom connectors will not implement this method but will instead rely on the AbstractConnector's provision method to do the plan parsing. | Splits the plan into individual actions for each request type (delete, create, update, enable, etc.) and calls other methods to provide the requested action. | | `delete()` `^` | Should delete the object from the application based on the native identifier. | Throws unsupported | | `create()` `^` | Should create an account (or group) in the application given a native identifier and a list of attribute values. | Throws unsupported | | `update()` `^` | Should update the values for the specified account or group, matched by native identifier. | Throws unsupported | | `enable()` `^` | Should enable the object on the application based on native identifier. | Throws unsupported | | `disable()` `^` | Should disable the object on the application based on native identifier. | Throws unsupported | | `unlock()` `^` | Should unlock the account on the application based on native identifier. | Throws unsupported | | `setPassword()` | Should set/reset the account password on the application, given a native identifier, new password, optional current password, and expiration date. | Throws unsupported | `*` - Required method `^` - These methods each accept a hashmap of options which can influence the operation. Any arguments passed in the request (within the provisioning plan) are passed to the target method by the `provision()` method to be used as needed by the connector. Methods can throw any of the following exceptions: `ConnectorException`, `AuthenticationFailedException`, `UnsupportedOperationException`, `ObjectAlreadyExistsException`, `ObjectNotFoundException`, or `ExpiredPasswordException`. ## Developing OpenConnector in Java To create a custom connector based on this framework: 1. Create the Java project, package, and class. 2. Write the methods for the required features. 3. Compile and deploy. ### Create the Project, Package, and Class 1. Start a new Java project. 2. Add all the OpenConnector SDK libraries to the build path for the build process. 3. Create a new package called "openconnector". 4. Create a new class in the openconnector package with the desired class name for the new connector. The following image illustrates how to do this in Eclipse, but any IDE can be used. > **Screenshot** > > [![Creating a Java Class]()]() ## Deploying in SailPoint To deploy a custom connector in SailPoint: 1. Create a Connector via the REST API. 2. Download the Connector Bundle and Update it via the REST API. 3. Configure Source in the SailPoint interface or via the REST API. 4. Upload Connector JAR(s) and Libraries. > [!NOTE] > > For more information on SailPoint's REST APIs, refer to [Best Practices: REST API Authentication]() and [REST API - Update Source (Partial)]() in the SailPoint Developer Community. The next sections reference the V3 REST APIs. For information on how to authenticate to REST APIs, refer to the [Developer Community](). The following topics are covered in this section: - [Create Connector](<#create-connector>) - [Update Connector Bundle](<#update-connector-bundle>) - [Configure Source](<#configure-source>) - [Upload Connector JAR(s) and Libraries](<#upload-connector-jars-and-libraries>) - [Test Connector](<#test-connector>) ### Create Connector Create the connector type calling the Create Connector REST API. `POST https://sailpoint.api.identitynow.com/v3/connectors` JSON body: ```json { "name": "ExampleConnector", "type": "custom_exampleName", "className": "sailpoint.connector.OpenConnectorAdapter", "directConnect": "true", "status": "released" } ``` Where: - `name` - This is the type of connector which you want to refer to this by. This is visible in the UI. - `type` - The connector type. If not specified, the name will default to 'custom' + name. - `className` - This is the fully qualified package and class name of the connector that is being written. - If you are implementing OpenConnector standard (what we recommend), then this will be set to `sailpoint.connector.OpenConnectorAdapter`. - `directConnect` - This will always be `true` if you are creating a custom connector. - `status` - This indicates the status of the connector. Each tenant can be configured to see different connector statuses. For implementer usage, set the status to `released`. ### Update Connector Bundle In the following examples, `scriptName` is the script name of the connector you created. If you are unsure, you can always call `GET https://sailpoint.api.identitynow.com/beta/connectors` to see all connectors in the system. You can use the unescaped content of the `applicationXml`, `correlationConfigXml`, and `sourceConfigXml` fields to create a corresponding XML file containing the content modifications. To update the bundles, use the following: - To update the `applicationXml`, use `PUT https://sailpoint.api.identitynow.com/v3/connectors/:scriptName/source-template` - To update the `correlationConfigXml`, use `PUT https://sailpoint.api.identitynow.com/v3/connectors/:scriptName/correlation-config` - To update the `sourceConfigXml`, use `PUT https://sailpoint.api.identitynow.com/v3/connectors/:scriptName/source-config` Use the XML file as a 'file' form-data, and the configurations will be deployed into the SailPoint cloud. ### Configure Source Use the defined connector to create a source. You can follow the steps described in the documentation for a [supported connector]() to create a source using the SailPoint UI. You may also leverage the admin source configuration page to configure any settings using the new user interface you defined via the user interface forms. ### Upload Connector JAR(s) and Libraries Once the connector and sources are defined, upload the packaged JAR files in the user interface. When you upload these, they are copied to the VA(s) which are associated with the particular source. > [!NOTE] > > This process may take a while to upload, especially when you have many VA cluster members. - Ensure that all third-party libraries that you use: - Are from an authentic or trusted source. - Do not incur legal obligations. - Are free from known security vulnerabilities. - Are compatible with the supported JDK versions shipped with VA (OpenJDK 11). - Custom connectors should upload all third-party JAR dependencies required by the connector with a few exceptions. Custom connectors should not upload or pack the following libraries or classes with their source, as these are the infrastructure libraries which are shipped with the platform. Uploading these can cause class loading or conflict errors. - OpenConnector framework classes or JAR - Responsible for providing connector infrastructure like interfaces and functionality control. - Any default connector bundle JAR. - `aspect*.jar` - Responsible to provide the aspect infrastructure. - `commons-logging*.jar`, `log4j-*.jar`, `slf4j-api*.jar` - Responsible to provide logging infrastructure. - `bsf*.jar`, `bsh*.jar` - Used to execute Rules. If any of the dependencies are missing in the uploaded connector JAR file, an error can occur during the test connection. The error shows which third-party library is missing. ### Test Connector Once complete, test the connector in the SailPoint interface. Run **Test Connection** and import accounts. # Troubleshooting If you encounter any of the following issues or errors, SailPoint recommends that you follow the guidance provided below to resolve the error before contacting SailPoint Support. For issues or errors that are not addressed in this connector guide, refer to the following resources for troubleshooting information: - [SailPoint Identity Services Documentation]() - [SailPoint Support Knowledge Base]() - [SailPoint Developer Community]() During development, when building a custom connector for the first time, SailPoint recommends that you create a development VA to use for debugging. The logging information that flows to `/home/sailpoint/log/ccg.log` should only be that of your connector. While debugging, follow the [instructions to enable debugging on VAs](). SailPoint recommends that you put `log.debug(...)` statements in your connector so that these are visible whenever debugging is enabled on the VAs. Post-development, the custom connectors can be deployed as normal using normal VAs for the particular tenants.