NEEDS UPDATE

Overview: 

we need a SCIM wrapper containing rest endpoints to apply SCIM operation on databases. User Database CRUD operation scripts and database details will be stored in a conf folder. Using this configuration we will be going to create SCIM schema and SCIM rest services to search, create, modify and delete User in the database table.

Objective:

  • Create a User Account for Database.
  • Modify a User Account for Database.
  • Remove a  User Account for Database.
  • Search All Users from a Database.
  • Search User by userId from a database.

Rest Endpoints:

GET Endpoints

These operations are used to retrieve information from the SCIM endpoint for databases.

--/ServiceProviderConfig

This endpoint returns the Service Provider Configuration see the specification below for its’ definition

Specification:https://tools.ietf.org/html/rfc7643#section-5

Example: https://tools.ietf.org/html/rfc7643#section-8.5

--/ResourceTypes

This endpoint returns the Resource Types supported by this service provider, see the specification below for the formal definition.

Specification: https://tools.ietf.org/html/rfc7643#section-6

Example: https://tools.ietf.org/html/rfc7643#section-8.6

--/Schemas

This endpoint returns the Schemas supported by this service provider, see the specification below for the formal definition.

Specification: https://tools.ietf.org/html/rfc7643#section-7

Example: https://tools.ietf.org/html/rfc7643#section-8.7

--/{resourceName}

This endpoint returns all the objects from the database for a resource having name resourceName.

/{resourceName}/{id}

This endpoint returns an individual object from database for a resource having name resourceName and identifies by id mentioned in URL.


--/Schemas/{id}

This endpoint returns the Schema identified by {id}

Specification: https://tools.ietf.org/html/rfc7644#section-3.4.1

POST Endpoints

--/{resourceName}

This post-operation should create a new object in the database for a resource having name resourceName from the SCIM data received as the request Body for this resource.

PUT Endpoints

--/{resourceName}/{id}

This PUT operation should replace an existing object in the database for a resource having name resourceName, identified by {id}, using the SCIM data received as request Body for this resource.

PATCH Endpoints

--/{resourceName}//{id}

This PATCH operation should modify an existing object in the database for a resource having name resourceName, identified by {id}, using the SCIM data received as the request Body for this resource.

DELETE Endpoints

--/{resource}/{id}

This DELETE operation should delete an existing object from the database for a resource having name resourceName, identified by {id}.


Configuration (conf folder)

All configuration should be placed into conf older which contains subfolders:

  1. schemas(Folder)
  2. scimConfigs(Folder)
  3. connection.json


connection.json

connection.json will contain databases connection details in below format


{
  "connection": {
    "driver_class": "com.mysql.cj.jdbc.Driver",
    "url": "jdbc:mysql://10.2.9.132:3306/db?useSSL=false",
    "user": "user",
    "password": "password",
    "dialect": "oracle",
    "table": "usr",
    "mapping": "false",
    "id": "username"
  }
}
CODE




schemas Folder

This folder will contain schema for the different resources used in scim Connector. The naming convention of each file should be <ResourceName>Schema.json.

A sample for AccountSchemas is given below


{
  "id": "urn:sath:params:scim:schemas:core:1.0:Account",
  "name": "Account",
  "description": "User Account",
  "attributes": [
    {
      "name": "Fname",
      "type": "string",
      "required": true
    },
    {
      "name": "Lname",
      "type": "string",
      "required": true
    },
    {
      "name": "username",
      "type": "string",
      "required": true
    },
    {
      "name": "displayName",
      "type": "string",
      "required": false
    },
    {
      "name": "emails",
      "type": "string",
      "required": true
    },
    {
      "name": "phones",
      "type": "string",
      "required": true
    }
  ],
  "meta": {
    "resourceType": "Schema",
    "location": "/v2/Schemas/urn:sath:params:scim:schemas:core:1.0:Account"
  }
}


CODE


A schema file will contain the following attributes
1. id: id of a schema. for sath defined schemas the id should be look like "urn:sath:params:scim:schemas:core:1.0:<ResourceName>".
2. name: name of the resource type for which this schema is defined.
3. description: the description of the schema.

4. attributes: the attributes of resource types the attributes is an object containing a name, type, required attribute which servers purpose of naming and define the type of each attribute and check whether the attribute is required or not.

5. meta: metadata of the schema containing resource type and location of the schema.


scimConfigs

This folder contains the configuration for each resource type(schema). The naming convention of each file should be <ResourceName>.json .

The sample file is like:

{
  "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
  "matching-attributes": [
    "username",
    "email"
  ],
  "attribute-map": {
    "Fname": {
      "attribute": "Fname",
      "type": "string"
    },
    "Lname": {
      "attribute": "Lname",
      "type": "string"
    },
    "givenName": {
      "attribute": "Fname",
      "type": "string"
    },
    "sn": {
      "type": "string",
      "query": ".Beta"
    },
    "displayName": {
      "type": "string",
      "attribute": "displayName"
    },
    "name": {
      "type": "string",
      "attribute": "displayName"
    },
    "username": {
      "attribute": "username",
      "type": "string"
    },
    "email": {
      "type": "string",
      "query": ".emails"
    },
    "phone": {
      "attribute": "phones",
      "type": "string"
    },
    "title": {
      "attribute": "title",
      "type": "string"
    },
    "department": {
      "attribute": "department",
      "type": "string"
    },
    "userType": {
      "attribute": "userType",
      "type": "string"
    },
    "organization": {
      "attribute": "organization",
      "type": "string"
    },
    "employeeNumber": {
      "attribute": "employeeNumber",
      "type": "string"
    },
    "manager": {
      "attribute": "manager",
      "type": "string"
    }
  },
  "scripts": {
    "insert": ["INSERT INTO usr (phone,email,username) VALUES('${phone}','${email}','${username}') "],
    "update": ["UPDATE usr set phone='${phone}',email='${email}'"],
    "delete": ["DELETE FROM usr"],
    "select": ["SELECT * FROM usr"],
    "mappingToExistingToResponse": [
      {
        "id": "${username}",
        "externalId": "${username}",
        "username": "${username}",
        "givenName": "${username}",
        "displayName": "${username}",
        "name": "${username}",
        "email": "${email}",
        "userType": "${username}",
        "title": "${username}",
        "department": "${username}",
        "organization": "${username}",
        "phone": "${phone}",
        "employeeNumber": "${username}"
      }
    ]
  },
  "configs": {
    "tableName": "usr",
    "MongoCollection":"Test",
    "MongoDataBase":"userappdb",
    "uniqueKey":"username"
  }
}

CODE


Thie file is a JSON object containing the following attributes:

schemas: schema id for which this configuration is defined. e.g for Account schema shown above the attribute value will be "urn:sath:params:scim:schemas:core:1.0:Account".

matching-attributes: the unique attribute name which can be used as the id for rest operation of scim.


attribute-map: attribute mapping for converting the scim schema which is coming as request body for each rest API to a separate conical object which can be used for target system CRUD operations. 

For each attribute, mapping can be one of the two types.

                              1.First Type 

                                                         conicalAttributeName: {

                                                                    "attribute": "scimAttributeName",

                                                           }


                             2. Second Type:

                                                        conicalAttributeName: {

                                                                    "query": "jq query to fetch data from scim json object",

                                                       }


scripts: This part will contain the target system native mapping for a different type of CRUD operations like insert update delete select.

                                            insert mapping for insertion operation. mapping should be string type formate.

                                            update mapping for update operation. mapping should be string type formate.

                                            delete mapping for deletion operation. mapping should be string type formate.

                                            select mapping for selection operation. mapping should be string type formate.

                                            mappingToExistingToResponse contains the mapping from native to intermediate JSON as a JSON formate.

For RDBMS databases the script format will be

"scripts": {
    "insert": ["INSERT INTO usr (phone,email,username) VALUES('${phone}','${email}','${username}') "],
    "update": ["UPDATE usr set phone='${phone}',email='${email}'"],
    "delete": ["DELETE FROM usr"],
    "select": ["SELECT * FROM usr"],
    "mappingToExistingToResponse": [
      {
        "id": "${username}",
        "externalId": "${username}",
        "username": "${username}",
        "givenName": "${username}",
        "displayName": "${username}",
        "name": "${username}",
        "email": "${email}",
        "userType": "${username}",
        "title": "${username}",
        "department": "${username}",
        "organization": "${username}",
        "phone": "${phone}",
        "employeeNumber": "${username}"
      }
    ]
  }
CODE


Note: all the above attributes are array to pass multiple mappings.

configs: this will contain configuration related to the target system.

for example for Databases config will like:

"configs": {
"tableName": "usr",
"MongoCollection":"Test",
"MongoDataBase":"userappdb",
"uniqueKey":"username"
}

3. How to add a new resource.


Steps:

  1. create a schema for resource in the schemas folder in a separate JSON file. schema structure is shown above.
  2. create a config JSON for attribute mapping, Scripts and conical resource creation in scimConfigs.
  3. add a connection.json containing LDAP server details if a connection.json does not exist.

we can call all rest endpoints like

GET- /ResourceName  → This endpoint returns all the information of Resource

GET - /ResourceName/{id}  → This endpoint returns the information of  individual Resource by {id}.

POST - /ResourceName ->This post-operation should create a new Resource from the SCIM data received as the request Body.

PUT - /ResourceName/{id} → This PUT operation should modify  the information of  individual Resource by {id}.

DELETE  /ResourceName/{id} → This DELETE operation should delete the information of individual Resource by {id}.


Example of the POST call for Resource Account for an LDAP based connector:

URL: http://localhost:8080/scim/v2/Account   

body: the body will contain all data for the resource we need to create.

{
"schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
"meta":{
"resourceType": "User",
"created":"2011-08-01T18:29:49.793Z",
"lastModified":"2011-08-01T18:29:49.793Z",
"location":"https://example.com/v2/Users/2819c223...",
"version":"W\/\"f250dd84f0671c3\""
},
"Fname":"Aman",
"Lname": "Singh",
"userName":"asingh",
"displayName":"Amar Singh",
"phone": "+1 5555551111",
"email": "amansingh@sath.com",
"title":"System Engineer",
"addresses":{
"region":"Kolkata",
"locality":"west-bengal",
"postalCode":"700064",
"countryCode":"IN",
"country":"India",
"streetAddress":"Street 31"
},
"department":"Research",
"userType":"EMP",
"organization":"Exelon",
"employeeNumber":"132356456",
"manager":"Alexa"
}


CODE

response: if resource creation is successful then we will return created schema of resource else error with error code.

{
"addresses": {
"streetAddress": "Street 31",
"postalCode": "700064",
"locality": "west-bengal",
"region": "Kolkata"
},
"manager": "",
"displayName": "Amar Singh",
"givenName": "Aman",
"externalId": "cn=Aman Singh,ou=People,dc=iamsath,dc=com",
"userName": "asingh",
"title": "System Engineer",
"employeeNumber": "132356456",
"emails": "amansingh@sath.com",
"phone": "+1 5555551111",
"meta": {
"location": "/v2/Schemas/urn:sath:params:scim:schemas:core:1.0:Account",
"resourceType": "Schema"
},
"organization": "Exelon",
"schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
"name": "Amar Singh",
"id": "cn=Aman Singh, ou=People, dc=iamsath, dc=com",
"userType": "EMP",
"department": "Research"
}
CODE


Example of PATCH call for Resource Account:

URL: http://localhost:8080/scim/v2/Account/amansingh@sath.com//   URL id should contain the value for identifying the resource uniquely and the attribute of this value should be one of the matching attributes of the config file.

body: the body will contain only for those data for the resource which we need to modify.

{
 "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
  "email": "akash@sath.com",
  "title":"System Engineer",
  "department":"Service",
  "userType":"EMP",
  "organization":"Sath"
}
CODE

response: if resource modification is successful then we will return created schema of resource else error with error code.

{
    "addresses": {
        "streetAddress": "Street 31",
        "postalCode": "700064",
        "locality": "west-bengal",
        "region": "Kolkata"
    },
    "manager": "",
    "displayName": "Amar Singh",
    "givenName": "Aman",
    "externalId": "cn=Aman Singh,ou=People,dc=iamsath,dc=com",
    "userName": "asingh",
    "title": "System Engineer",
    "employeeNumber": "132356456",
    "emails": "amansingh@sath.com",
    "phone": "+1 5555551111",
    "meta": {
        "location": "/v2/Schemas/urn:sath:params:scim:schemas:core:1.0:Account",
        "resourceType": "Schema"
    },
    "organization": "Sath",
    "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
    "name": "Amar Singh",
    "id": "cn=Aman Singh, ou=People, dc=iamsath, dc=com",
    "userType": "EMP",
    "department": "Service"
}

CODE

Example of PUT call for Resource Account:

URL: http://localhost:8080/scim/v2/Account/amansingh@sath.com//   URL id should contain the value for identifying the resource uniquely and the attribute of this value should be one of the matching attributes of the config file.

body: the body will contain all data for the resource we need to replace. This body will contain the whole document of Account to update here.

 {
 "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
  "meta":{
    "resourceType": "User",
    "created":"2011-08-01T18:29:49.793Z",
    "lastModified":"2011-08-01T18:29:49.793Z",
    "location":"https://example.com/v2/Users/2819c223...",
    "version":"W\/\"f250dd84f0671c3\""
  },
  "Fname":"Aman",
  "Lname": "Singh",
  "userName":"asingh",
  "displayName":"Amar Singh",
  "phone": "+1 5555551111",
  "email": "amansingh@sath.com",
  "title":"Senior System Engineer",
  "addresses":{
  	"region":"Kolkata",
  	"locality":"west-bengal",
  	"postalCode":"700064",
  	"countryCode":"IN",
  	"country":"India",
  	"streetAddress":"Street 31"
  },
  "department":"Research",
  "userType":"EMP",
  "organization":"Exelon",
  "employeeNumber":"132356456",
  "manager":"Alexa"
}
CODE

response: if resource replacement is successful then we will return created schema of resource else error with error code.

   {
    "addresses": {
        "streetAddress": "Street 31",
        "postalCode": "700064",
        "locality": "west-bengal",
        "region": "Kolkata"
    },
    "manager": "",
    "displayName": "Amar Singh",
    "givenName": "Aman",
    "externalId": "cn=Aman Singh,ou=People,dc=iamsath,dc=com",
    "userName": "asingh",
    "title": "Senior System Engineer",
    "employeeNumber": "132356456",
    "emails": "amansingh@sath.com",
    "phone": "+1 5555551111",
    "meta": {
        "location": "/v2/Schemas/urn:sath:params:scim:schemas:core:1.0:Account",
        "resourceType": "Schema"
    },
    "organization": "Exelon",
    "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
    "name": "Amar Singh",
    "id": "cn=Aman Singh, ou=People, dc=iamsath, dc=com",
    "userType": "EMP",
    "department": "Research"
}


CODE

Example of GET call for Resource Account:

URL: http://localhost:8080/scim/v2/Account/amansingh@sath.com//   URL id should contain the value for identifying the resource uniquely and the attribute of this value should be one of the matching attributes of the config file.

response: if resource searching is successful then we will return the schema of resource else error with error code.

 {
    "addresses": {
        "streetAddress": "Street 31",
        "postalCode": "700064",
        "locality": "west-bengal",
        "region": "Kolkata"
    },
    "manager": "",
    "displayName": "Amar Singh",
    "givenName": "Aman",
    "externalId": "cn=Aman Singh,ou=People,dc=iamsath,dc=com",
    "userName": "asingh",
    "title": "Senior System Engineer",
    "employeeNumber": "132356456",
    "emails": "amansingh@sath.com",
    "phone": "+1 5555551111",
    "organization": "Exelon",
    "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
    "name": "Amar Singh",
    "id": "cn=Aman Singh, ou=People, dc=iamsath, dc=com",
    "userType": "EMP",
    "department": "Research"
}

CODE

Example of DELETE call for Resource Account:

URL: http://localhost:8080/scim/v2/Account/amansingh@sath.com//   URL id should contain the value for identifying the resource uniquely and the attribute of this value should be one of the matching attributes of the config file.

response: if resource deletion is successful then we will return the Deleted message else error with error code.

 Deleted
CODE

Example of GET ALL call for Resource Account:

URL: http://localhost:8080/scim/v2/Account//   

response: if all resource searching is successful then we will return the schema of all resources else error with error code.

 {
    "Account": [
        {
            "addresses": {
                "streetAddress": "",
                "postalCode": "",
                "locality": "",
                "region": ""
            },
            "manager": "",
            "displayName": "Jane Doe",
            "givenName": "",
            "externalId": "cn=Jane Doe,ou=People,dc=iamsath,dc=com",
            "userName": "",
            "title": "",
            "employeeNumber": "",
            "emails": "",
            "phone": "",
            "organization": "Google",
            "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
            "name": "Jane Doe",
            "id": "cn=Jane Doe, ou=, dc=iamsath, dc=com",
            "userType": "",
            "department": ""
        },
        {
            "addresses": {
                "streetAddress": "null",
                "postalCode": "700064",
                "locality": "west-bengal",
                "region": "Kolkata"
            },
            "manager": "",
            "displayName": "Aman Singh",
            "givenName": "akash",
            "externalId": "cn=akash Sharma,ou=People,dc=iamsath,dc=com",
            "userName": "akash",
            "title": "Engineer",
            "employeeNumber": "null",
            "emails": "asingh@sath.com",
            "phone": "+1 5555551111",
            "organization": "Exelon",
            "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
            "name": "Aman Singh",
            "id": "cn=akash Sharma, ou=People, dc=iamsath, dc=com",
            "userType": "EMP",
            "department": "Research"
        },
        {
            "addresses": {
                "streetAddress": "Street 31",
                "postalCode": "700064",
                "locality": "west-bengal",
                "region": "Kolkata"
            },
            "manager": "",
            "displayName": "Amar Singh",
            "givenName": "Aman",
            "externalId": "cn=Aman Singh,ou=People,dc=iamsath,dc=com",
            "userName": "asingh",
            "title": "Senior System Engineer",
            "employeeNumber": "132356456",
            "emails": "amansingh@sath.com",
            "phone": "+1 5555551111",
            "organization": "Exelon",
            "schemas": "urn:sath:params:scim:schemas:core:1.0:Account",
            "name": "Amar Singh",
            "id": "cn=Aman Singh, ou=People, dc=iamsath, dc=com",
            "userType": "EMP",
            "department": "Research"
        }
    ],
    "schemas": "urn:sath:params:scim:schemas:core:1.0:Account"
}
CODE

Deployment:

This project can be deployed using docker via git pipeline.