Example custom provisioner for web service

Example custom provisioner for web service

Valid for Grouper v2.6.18+

This is the lite version of this implementation

This is an example of how an institution would make a provisioner that is not included in the Grouper Provisioning Framework.  If you have something that is generic that others can leverage, maybe we should add it to the Grouper product.  If your needs are specific to your institution, this is what you need to do.

This example is based on requirements posted to the slack channel from University of Minnesota.

All the code is included in Grouper, so you can see the source code.  Though this provisioner is not enabled, it is intended as an example.

Example WS source code

Example WS test source code

 

Table of contents

WS spec

The first step is to identify and document the WS spec.  Proof of concepts of calling the WS could be done.

In this case there is one operation, a REPLACE of members for a group

It is assumed that authentication is basic auth.

HTTP method

PUT /path/endpoint/<SOURCE>/<ROLE>

HTTP body

<?xml version="1.0"?> <ExternalRoleRequest> <Users> <netID>USER1234</netID> <netID>USER5678</netID> <netID>USER9012</netID> <netID>USER3456</netID> </Users> </ExternalRoleRequest>

 

Design the target representation of objects

Plan out which operations of the WS will be used for Grouper and how.

There is one operation, so we will use that

The <SOURCE> will be configured for the provisioner instance.  If you want to provision to multiple sources, make another provisioner.  This is an assumption and could be metadata or based on a parent folder or whatever.

The <ROLE> will be the sole attribute of the target representation of the group.  We will translate this from the extension of the group.  Again this is an assumption.  Figure out how you want to translate based on your requirements.

Target group representation

Attribute

Translation

Notes

role

group extension

The provisioner will put this attribute in the role spot in the URL

The provisioning type will be membershipObjects.  We could have probably used groupAttributes, but this is what we did.  The membershipObject will have two attributes.

Target membership representation

Attribute

Translation

Notes

role

group extension

The provisioner needs this to differentiate memberships from one group to another.  Needs a tuple

netID

entity subjectIdentifier

The main subject identifier defaults to the subject source subjectIdentifier0.  Will make the XML based on these

We are not selecting or changing entities and there is a straight translation from grouper provisioning entities (subjectIdentifier0) so we don't need to define a target representation of entities.

Custom external system

Note, this is optional.  You dont need an external system to make your provisioner.  It is nice to have one to see it in the UI, test it, re-use it, etc.  If you dont create an external system, just reference whatever properties you need from a grouper config file, and set those in the config file or configuration screen in the UI.

In this case we could probably re-use a built in Grouper basic auth WS external system.  However, to show how to make your own, we will just implement one anyways

  1. Implement the external system - note, the test method in this case uses the DAO implementation below... this is very circular.  You could implement something simple here instead if you like...

  2. Register this external system in grouper.properties (config id doesnt matter)

    grouperExtraExternalSystem.exampleWsExternalSystem.class = edu.internet2.middleware.grouper.app.provisioningExamples.exampleWsReplaceProvisioner.ExampleWsExternalSystem



  3. Register a file which has the spec for the external system wizard

    1. The path must be the same path as your External System implementation (identify some java package that is your own).  So you might start with edu/upenn/penngroups/myProvisioner if you were at penn...

    2. The filename is: grouper.extraMetadata.externalSystem.<externalSystemConfigIdAbove>.properties


      edu/internet2/middleware/grouper/app/provisioningExamples/exampleWsReplaceProvisioner/grouper.extraMetadata.externalSystem.exampleWsExternalSystem.properties
  4. Then in that file, identify which properties you need.  In this case we will implement testing of the external system which will just all a method on it.  In this case we will just replace a group memberships.  In yours you might have a less heavy method to call.

    1. Look in the base properties files of Grouper for examples of the metadata (the JSON commented out above each property).  Note this file has all commented out properties, not actual properties

      ############################################ ## example external system ############################################ # endpoint prefix # {valueType: "string", required: true} # grouper.exampleWsExternalSystem.myExampleExternalSystem.endpointPrefix = # user name # {valueType: "string", required: true} # grouper.exampleWsExternalSystem.myExampleExternalSystem.userName = # password # {valueType: "password", sensitive: true, required: true} # grouper.exampleWsExternalSystem.myExampleExternalSystem.password = # test source # {valueType: "string", required: false} # grouper.exampleWsExternalSystem.myExampleExternalSystem.testSource = # test role # {valueType: "string", required: false} # grouper.exampleWsExternalSystem.myExampleExternalSystem.testRole = # comma separated net ids # {valueType: "string", required: false} # grouper.exampleWsExternalSystem.myExampleExternalSystem.testNetIds =
  5. You can externalize that text in grouper.text.en.us.properties

    config.ExampleWsExternalSystem.title = Example WS external system config.ExampleWsExternalSystem.attribute.endpointPrefix.label = Endpoint config.ExampleWsExternalSystem.attribute.endpointPrefix.description = This is the prefix of the endpoint before the source and role, e.g. http://localhost:8080/grouper/mockServices/exampleWs config.ExampleWsExternalSystem.attribute.userName.label = Username config.ExampleWsExternalSystem.attribute.userName.description = Basic auth username config.ExampleWsExternalSystem.attribute.password.label = Password config.ExampleWsExternalSystem.attribute.password.description = Basic auth password config.ExampleWsExternalSystem.attribute.testSource.label = Test source config.ExampleWsExternalSystem.attribute.testSource.description = When hitting the 'test' button this is the source that will be sent config.ExampleWsExternalSystem.attribute.testRole.label = Test role config.ExampleWsExternalSystem.attribute.testRole.description = When hitting the 'test' button this is the role that will be sent config.ExampleWsExternalSystem.attribute.testNetIds.label = config.ExampleWsExternalSystem.attribute.testNetIds.description = When hitting the 'test' button these are the netID's that will be sent

     

  6. Now you can see the external system in the UI and configure one



  7. Test the external system (note, this relies on the Mock and provisioner implementation below)