Implementation of the Target System Connector

Pseudocode

Target System Connector

public String postResource(String resourceName, String resourceInstance) {
	connect to the target system
	create a new object in the target system with the details given in the request body
	return the unique ID of the object created in the target system
}

public String patchResource(String resourceName, String resourceInstance, String id){
	connect to the target system
	retrieve the resource from the target system with the id
	update the JSON object retrieved from target system with the JSON object in the resource body - additional attributes must be added and existing attributes must be updated
	replace the resource in the target system with the newly created JSON object
	Update the resource in the target system with the details in the request body
}

public String putResource(String resourceName, String resourceInstance, String id) {
	connect to the target system
	replace the resource in the target system with the given id with the object in the request body
}

public String deleteResource(String resourceName, String id) {
	connect to the target system
	delete the resource in the target system with the given id
}

public String getResourceById(String resourceName, String id) {
	connect to the target system
	get the resource instance matching the resource name and id
	return a JSON object conatining the resource instance
}

public String searchResource(String resourceName, String filters) {
	if the filter parameter is empty 
		return all the instances of the given resource types are returned
	return the list of resource objects matching the filter
}

public String getSchema() {
	return a JSON object with the schema definition
}

JAVA

Connector Implementation

The target system connector interface needs to be implemented for every resource type separately. There should be separate classes for each resource type supported by the connector

Spring qualifier needs to be added for the purpose of instantiating the right resource type implementation. Please see the following example where there are two resource types - Account and Entitlement

Connector implementation

//Account implementation
@Service("Account") //name of the qualifier should match the IDHUB resource type for connector
public class AccountResourceConnector implements TargetSystemConnector { 
	//All the methods defined in the interface needs to be overriden
}

//Entitlement implementation
@Service("Entitlement") //name of the qualifier should match the IDHUB resource type for connector
public class EntitlementResourceConnector implements TargetSystemConnector {  //name of the class can be anything
	//All the methods defined in the interface needs to be overriden
}
JAVA

Configuration

Each splice have one conf directory which will keep 2 subdirectories as schemas and scim.

Directory "schemas"

This directory keeps all the resources. For each resource, there will be a file.

The schema structure looks like below-

{
  "id": "urn:sath:params:scim:schemas:core:1.0:Account",
  "name": "Account",
  "description": "User Account",
  "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
  "attributes": [
    {
      "name": "DisplayName",
      "type": "string",
      "required": true
    },
    {
      "name": "UserLogin",
      "type": "string",
      "required": true
    },
    {
      "name": "PhoneNumber",
      "type": "string",
      "required": true
    },
    {
      "name": "email",
      "type": "string",
      "required": true
    }
  ],
  "meta": {
    "resourceType": "Schema",
    "location": "/v2/Schemas/urn:sath:params:scim:schemas:core:1.0:Account"
  },
  "matching-attributes": [
    "uid",
    "mail"
  ],
  "attribute-map": {
   "givenName": {
      "attribute": "DisplayName",
      "type": ""
    },
    "sn": {
      "type": "",
      "query": ".displayName"
    },
    "displayName": {
      "attribute": "DisplayName"
    },
    "name": {
      "attribute": "DisplayName"
    },
    "id": {
      "attribute": "UserLogin"
    },
   "email": {
      "attribute": "email",
      "type": "",
      "query": "{mail: .emails[].value}"
    },
    "phone": {
      "attribute": "PhoneNumber",
      "type": ""
    },
   "entitlements": {
      "attribute": "entitlements",
      "type": ""
    },
    "manager": {
      "attribute": "manager",
      "type": ""
    }
  },
  "scripts": {
    "insert": [
      "dn: cn=${this.uid},ou=${this.ou},dc=iamsath,dc=com\nobjectClass: top\n#person\nobjectClass: person\nsn: ${scim.givenName}\ncn: ${scim.id}\ntelephoneNumber: ${scim.phone}\nseeAlsodescription:\n#org person\nobjectClass: organizationalPerson\nx121Address:\nregisteredAddress:\ndestinationIndicator:\npreferredDeliveryMethod:\ntelexNumber:\nteletexTerminalIdentifier:\ninternationaliSDNNumber:\nfacsimileTelephoneNumber:\nphysicalDeliveryOfficeName:\nou: People\n# inet org person\nobjectClass: inetorgperson\naudio:\nbusinessCategory:\ncarLicense:\ndisplayName: ${scim.displayName}\ngivenName: ${scim.givenName}\nhomePhone: ${scim.phone}\ninitials:\nlabeledURI:\nmail: ${scim.email}\no: ${scim.organization}\npager:\nroomNumber:\nsecretary:\nuid: ${scim.id}"
    ],
    "update": [
      "dn: cn=${this.uid},ou=${this.ou},dc=iamsath,dc=com\nobjectClass: top\n#person\nobjectClass: person\nsn: ${scim.givenName}\ncn: ${scim.id}\ntelephoneNumber: ${scim.phone}\nseeAlsodescription:\n#org person\nobjectClass: organizationalPerson\nx121Address:\nregisteredAddress:\ndestinationIndicator:\npreferredDeliveryMethod:\ntelexNumber:\nteletexTerminalIdentifier:\ninternationaliSDNNumber:\nfacsimileTelephoneNumber:\nphysicalDeliveryOfficeName:\nou: People\n# inet org person\nobjectClass: inetorgperson\naudio:\nbusinessCategory:\ncarLicense:\ndisplayName: ${scim.displayName}\ngivenName: ${scim.givenName}\nhomePhone: ${scim.phone}\ninitials:\nlabeledURI:\nmail: ${scim.email}\no: ${scim.organization}\npager:\nroomNumber:\nsecretary:\nuid: ${scim.id}"
    ],
    "delete": [],
    "select": [],
    "mappingToExistingToResponse": [
      {
        "id": "cn=${ldif.cn}, ou=${ldif.ou}, dc=iamsath, dc=com",
        "externalId": "${ldif.dn}",
        "userName": "${ldif.uid}",
        "givenName": "${ldif.givenName}",
        "displayName": "${ldif.displayName}",
        "name": "${ldif.displayName}",
        "emails": "${ldif.mail}",
        "phone": "${ldif.telephoneNumber}",
        "manager": "${ldif.manager}",

      }
    ]
  },
  "configs": {
    "OBJECT_CLASS_PRESENT": "(objectClass=person)"
  }
}

JAVA

Directory "scim"

This directory keeps ServiceProviderConfiguration.

The content looks like below-

{
  "schemas": [
    "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"
  ],
  "documentationUri": "https://www.sath.com/idhub/documentation",
  "patch": {
    "supported": false
  },
  "bulk": {
    "supported": false,
    "maxOperations": 0,
    "maxPayloadSize": 0
  },
  "filter": {
    "supported": false,
    "maxResults": 0
  },
  "changePassword": {
    "supported": false
  },
  "sort": {
    "supported": false
  },
  "etag": {
    "supported": false
  },
  "authenticationSchemes": [
    {
      "name": "OAuth Bearer Token",
      "description": "Authentication scheme using the OAuth Bearer Token Standard",
      "specUri": "http://www.rfc-editor.org/info/rfc6750",
      "documentationUri": "no documentation",
      "type": "oauthbearertoken",
      "primary": true
    },
    {
      "name": "HTTP Basic",
      "description": "Authentication scheme using the HTTP Basic Standard",
      "specUri": "http://www.rfc-editor.org/info/rfc2617",
      "documentationUri": "no documentation",
      "type": "httpbasic"
    }
  ],
  "meta": {
    "location": "scim/v2/ServiceProviderConfig",
    "resourceType": "ServiceProviderConfig",
    "created": "2019-09-03T00:00:00Z",
    "lastModified": "2019-09-03T00:00:00Z",
    "version": "W\/\"3694e05e9dff594\""
  }
}

JAVA

Splice properties file

This is application.yml file. This contains Splice related metadata along with Target system-related connection information.

spring:
  profile: splice
  name: ldap-splice
  environment: test
  version: 1.0.0
target-system:
  name: ldap
  host: 10.2.9.80
  port: 389
  username: cn=Directory Manager
  password: <Encrypted Password>
  searchbase: dc=iamsath,dc=com
  newuserbase:


YML