Splice Design
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
}
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
}
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)"
}
}
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\""
}
}
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: