Revision History
Description |
Author |
Version |
Date |
Initial Creation |
Scott Fehrman |
0.9.0 |
September 2006 |
Update for release |
Scott Fehrman |
1.0.0 |
August 2007 |
Update for release, move to wiki |
Scott Fehrman |
1.1.0 |
August 2008 |
Introduction:
Project Open Provisioning ToolKit (OpenPTK) contains the core infrastructure, service modules and sample applications.
Core Infrastructure:
The core infrastructure is based on a three tier model; Consumer Tier, Framework Tier and Service Tier.
- Consumer Tier: Provides a collection of Application Programming Interfaces (APIs). These APIs include a Java API, Java Server Page (JSP) Tag Library (taglib) and a WSDL-based web service.
- Framework Tier: Provides core operation facilities such as configuration, context management, attribute translation, service management and logging.
- Service Tier: Defines a service provider interface (SPI) to back-end provisioning solutions.
Service Modules:
Project OpenPTK is designed to support multiple different provisioning solutions, through the use of a Service Provider Interface (SPI). A given provisioning solution can be support by implementing the Service Tier's SPI.
Sample Applications:
A number of sample application are provide. These samples applications demonstrate various capabilities:
Command Line Interface (CLI) |
A stand-alone Java application that uses the Java API to provide an interactive command line interface that support user provisioning operations. |
User Management Lite (UML) |
A HTML/JSP web application that uses the JSP Tag Library. UML has web interfaces for Self Service, User Administration and Forgotten Passwords. UML can be easily customized by editing JSP and CSS files. |
Provision Person Web Service |
A WSDL-based web service that provides user provisioning operations. Applications an development tools (e.g. NetBeans, SOAPUI) can consume the deployed web service. |
Provisioning Portlets |
A collection of JSR-168 portlets that can be included into Portal services that support JSR-168 portlets. The collection contains a Forgotten Password, Self Service and User Management portlets. |
Project OpenPTK is a set of tools that Web developers and Java developers can use to create custom identity focused applications . Project OpenPTK provides an abstraction to the back-end services. Developers don't need to worry about the details of a specific provisioning interface. Project OpenPTK allows the developer to focus on the end-user (presentation tier) interface of their application. Project OpenPTK's Consumer Tier provides interfaces that use abstract representations of identity Subjects (e.g. People). Project OpenPTK is designed using a messaging architecture where requests/responses are passed from the Consumer Tier, through the Framework Tier, to the Service Tier, and back again. The Framework Tier handles the incoming messages (Requests), sends them to the configured back-end Service, and handles the return of messages (Responses).
Web developers and Portal developers can leverage the Consumer Tier's Java Server Pages (JSP) Tag Library to easily implement provisioning functions. Applications built using the Consumer Tier interfaces are separated from the actual provisioning back-end implementation. A single application can be built that uses one or more back-end Services.
Java developers can create new (or extend) Services to support specific back-end provisioning requirements. Again, the end-user application uses the Consumer Tier, and can be easily re-configured to use other Services as they become available.
Projects - Packages - Output:
Mapping of Netbeans projects to Java packages (if applicable) and then to output artifacts.
NetBeans Projects |
Java Packages |
Apps-CLI |
org.openptk.app.prov.cli |
Apps-Portlets |
org.openptk.app.prov.portlets |
Apps-UserManagementLite |
org.openptk.app.prov.uml |
Apps-WebServiceWSDL |
org.openptk.app.prov.webservice
org.openptk.app.prov.webservice.generated |
Apps-Consumer-Taglib |
org.openptk.provision.taglib |
Provision-Framework |
org.openptk.provision.authen
org.openptk.provision.common
org.openptk.provision.debug
org.openptk.provision.definition
org.openptk.provision.logging
org.openptk.provision.spi
org.openptk.provision.transform |
OpenPTK-Service-JDBC |
org.openptk.provision.spi |
OpenPTK-Service-JNDI |
org.openptk.provision.spi |
OpenPTK-Service-SPML |
org.openptk.provision.spi |
Samples-JavaAPI |
org.openptk.sample.prov.api |
Samples-Taglib |
org.openptk.sample.prov.taglib |
Consumer Tier:
Project OpenPTK's Consumer Tier provides a collection of utilities, services and APIs that communicate with the Framework Tier abstracted components. The Consumer Tier provides a Java Server Pages Tag Library (taglib) that is used by Web page designers to perform provisioning tasks. A set of Java APIs are exposed at this tier which allows the Java developer to leverage Project OpenPTK. The Web Service allows other Web Service-based client applications to access Project OpenPTK through the use of standards based XML/SOAP and a WSDL.
JSP Tag Library Interface:
A web-site developers usually focus on the user experiences, site navigation and the applications "look and feel". One way to access Java APIs are to insert actual Java code into a Java Server Page (JSP). This is not considered to be a "best practice", it merges complex business/technical logic into the Presentation Tier (HTML/JSP). This makes the application hard to maintain and some Web developers may not be comfortable having Java code embedded within a web page.
Project OpenPTK provides a standards-based Java Server Pages (JSP) Tag Library for performing provisioning tasks. Instead of placing complex Java code in a web-page, simple XML-style tags are used. Web developers that have used other JSP Taglibs, like the Java Standard Tag Library (JSTL), will be comfortable using Project OpenPTK's taglib.
Project OpenPTK's Consumer Tier, Web Page Interface (WPI), is designed using standard JSP tag library specifications. The WPI includes the JSP tag library description (tld) file and a complete set of tag implementations. The tag library categories include:
Configuration:
Tag |
Description |
Syntax |
setConfiguration |
define application configuration |
<ptk:setConfiguration var="..." uri="..."/> |
setSubject |
Create a new subject using the specified Configuration and Context (from the Configuration) |
<ptk:setSubject configuration="..." context="..." var="..."/> |
debug |
get / dump debug information (currently under development) |
<ptk:debug var="..."/> |
Provisioning:
Tag |
Description |
Syntax |
doCreate |
create a new subject |
<ptk:doCreate subject="..." input="..." output="..."/> |
doRead |
read a single subject |
<ptk:doRead subject="..." input="..." output=".."/> |
doUpdate |
update a subject |
<ptk:doUpdate subject="..." input="..." output="..."/> |
doDelete |
delete a subject |
<ptk:doDelete subject="..." input="..." output="..."/> |
doSearch |
search for one or more subjects |
<ptk:doSearch subject="..." input="..." output="..."/> |
Password Management:
Tag |
Description |
Syntax |
doPasswordChange |
user specifies a new password |
<ptk:doPasswordChange subject="..." input="..." output="..."/> |
doPasswordReset |
system resets passwords |
<ptk:doPasswordReset subject="..." input="..." output="..."/> |
authenticate |
perform authentication |
<ptk:authenticate type="" subject="" input="" output=""/> |
Input - Output - Attribute:
Tag |
Description |
Syntax |
addValue |
Add a value to a predefined Attribute |
<ptk:addValue input="..." attribute="..." value="..."/> |
getAttribute |
Get an Attribute from the Output |
<ptk:getAttribute var="..." name="..." output="..."/> |
getAttributesList |
Get the List of Attributes from the Output |
<ptk:getAttributesList var="..." result=".."/> |
getName |
Get the name of the Attribute |
<ptk:getName var="..." attribute="..."/> |
getProperty |
Get the specified Property from either a Result or Output |
<ptk:getProperty name="..." var="..." [ output="..." | result="..." ] /> |
getResult |
Gets a single (first) Result from the Output |
<ptk:getResult var="..." output="..." /> |
getResultsList |
Gets a List of Results from the Output |
<ptk:getResultsList var="..." output="..." sizevar="..." /> |
getType |
Gets the type (as a String) of the Attribute |
<ptk:getType var="..." attribute="..."/> |
getUniqueId |
Get the UniqueId from the Result. If the "var" is not set, then the value will be sent inline. |
<ptk:getUniqueId [ var="..." ] result="..." /> |
getValue |
Get the specified (named) value from the Output. If the "var" is not set, then the value will be sent inline. |
<ptk:getValue [ var="..." ] [ attribute="..." | output="..." | result="..." ] name='...'/> |
getValuesList |
Gets the List of Values from the specified Attribute |
<ptk:getValuesList attribute="..." var="..." sizevar="..."/> |
setAttribute |
Creates an Attribute with the specified key and value and adds (sets) it to the Input |
<ptk:setAttribute input="..." key="..." value="..."/> |
setInput |
Creates an Input with the specified name. |
<ptk:setInput var="..."/> |
setProperty |
Set property on an Input |
<ptk:setProperty input="..." key="..." value="..."/> |
setQuery |
Create a Query and add (set) it to an Input |
<ptk:setQuery input="..." name="..." value="..." type="..." var="..."/> |
setUniqueId |
Sets the unique identifier for an Input |
<ptk:setUniqueId input="..." value="..."/> |
Utility:
Tag |
Description |
Syntax |
getInformation |
Get the specified information from the Element |
<ptk:getInformation type="..." element="..."/> |
| Handling an Error condition: Most of the tags will set the variable ptkError to String that has a length greater than 1. |
Adding provisioning operations to a JSP web application is easy once Project OpenPTK is configured in your environment. Please reference the Project OpenPTK, Installation/Configuration Guide for details. The JSP example below illustrates how Project OpenPTK tags can be used to create a user:
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://www.openptk.org/provision/taglib" prefix="ptk"%>
<ptk:setConfiguration var="cfg" uri="${configXML}"/>
<ptk:setSubject configuration="cfg" context="CustomerProduction" var="mysubject"/>
<ptk:setInput var="myinput"/>
<ptk:setAttribute input="myinput" key="firstname" value="${param.fname}"/>
<ptk:setAttribute input="myinput" key="lastname" value="${param.lname}"/>
<ptk:setAttribute input="myinput" key="email" value="${param.email}"/>
<ptk:doCreate subject="mysubject" input="myinput" output="myoutput"/>
- <%@taglib ...> maps Project OpenPTK's taglib to the prefix name of "ptk".
- <ptk:setConfiguration ...> establish preferences and connectivity to back-end systems through the use of a property file.
- <ptk:setSubject ...> defines a "person" subject, given the name "varsubject".
- <ptk:setInput ...> defines a "input" object. The input object is used to hold information that will be used by one of the provisioning tags.
- <ptk:setAttribute ...> used to define attributes (key/value) that are added to the Input.
- <ptk:doCreate ...> This tag performs the provisioning operation. This tag performs the create operation of the subject. The results of the tag's operation is returned in an output object.
All of the tags are implemented in the org.openptk.provision.taglib Java package. The diagram below lists all the tags in the library. Each tag sub-classes a base class called ProvisionTag. The ProvisionTag abstract class defines a common set of variables and methods that are used by all of the tags. The ProvisionTag supports the JSP taglib architecture by extending the SimpleTagSupport class. Developers that want to create new provisioning tags should extend the ProvisionTag class.
Command Line Interface:
The provisioning command line interface (CLI) is a Java application that utilizes Project OpenPTK's Consumer Tier Java API. The provisioning CLI is a single command that performs basic provisioning operations:
OpenPTK CLI
ptk -h
Usage: ptk <action> [global_options] [action_options]
The accepted values for action are:
search Search the service based on query
read Read the service for particular entry
create Create entry on the service
update Update entry on the service
delete Delete entry on the service
config Conguration Utilities
For more info on each action and options, use help
Example: ptk search -h
The accepted values for global_options are:
-C <context> -- Context to use. ptk config list-contexts for help
-c <config_file> -- Configuration File URL or File (xml)
Optionally set environment variable PTK_CONFIG
-h -- Show usage information.
These CLI tool can be used interactively or within operating system scripting languages to automate provisioning tasks.
Java Application Programing Interface:
There are situations where an End-User application needs to communicate directly with a Java API. The developer of a Java Swing-based or command-line application can use Project OpenPTK's Consumer Tier, Java APIs to perform provisioning operations.
Java applications interact with Project OpenPTK's Consumer Tier primarily through the Subject class. The Subject is created through the use of a configuration object. The Configuration object will initialize support utilities (logging and debugging), start the configured Service Tier and handle the processing of Input / Output objects with the Subject. The diagram below outlines the interaction of Project OpenPTK's Java Interface.
Project OpenPTK's Java API uses the following steps:
- Create the Configuration:
// ptk.xml, Project OpenPTK's configuration file
Configuration cfg = new Configuration("openptk.xml");
- Create the Subject and Inputs:
SubjectIF subject = cfg.getContextSubject();
Input input = new Input();
input.addAttribute("firstname","Bob");
input.addAttribute("lastname","Smith");
- Have Subject perform the operation:
Output output = subject.doCreate(Input);
The Project OpenPTK Development Guide contains a detailed example of how to use the Consumer Tier Java APIs.
WSDL-based Web Service Interface:
DETAIL AND DIAGRAMS NEEDED
JSR-168 Portlet Interface:
The sample Provisioning Portlets implement the JSR-168 Portlets interface by extending the standard GenericPortlet Java class. Three sample JSR-168 Portlets are provided which demonstrate different provisioning functions.
Portlet |
Description |
Forgotten Password |
Provides a portlet channel that allows the user to enter their name and responses to challenge questions. After the questions are answered (correctly), the user can change their password |
Self Service |
Using the authenticated user information, the user's personal information can be managed. The user can update some of their own data and change their own password. |
User Admin |
A simple to use interface for managing users in the repository. User can be created, updated, deleted. The administrator can also change or reset the users password. |
- ProvisioningPortlet an abstract class that does implement the following JSR-168 interface methods: init(), getTitle(). It provides the core methods, used by sub-clasess, that leverage the OpenPTK Java APIs.
- Forgotten Password extends ProvisioningPortlet and implements these JSR-168 methods processAction(), doView(). doHelp()
- Self Service extends ProvisioningPortlet and implements these JSR-168 methods processAction(), doView(). doHelp()
- User Admin extends ProvisioningPortlet and implements these JSR-168 methods processAction(), doView(). doHelp()
- PortalUser and PortalUserEntryDN support the mapping of a Portal Servers definition of a "user id" to OpenPTK uniqueId.
- PortalState manage the state of each Portal instance. Each user has a unique Portal Id which is used to store their state information.
|
Framework Tier:
The Framework Tier provides core capabilities that are used to manage the interaction between the Consumer Tier and the Service Tier. The Framework Tier provides:
- Context architecture for managing Services and handling events
- Request / Response architecture for processing provisioning events
- Reusable services such as logging and debugging
- Base Components that provide consistent capabilities
The Framework Tier contains the following Java packages
The Common package:
org.openptk.provision.common
Component:
The Component class is a foundation class that is used as a base-class more many of the other classes within the OpenPTK. The Component class provides many convenient attributes with related getter/setter methods:
- Attribute
- Category
- Description
- Properties
- State information
- Status information
- Error flag
- Debug flag / Debug Level
- Note
- Items
- Sort
- Timestamps
- UniqueId
A Component can have one of the following States:
State |
Description |
Null |
uninitialized |
New |
Just created |
Ready |
ready for use |
Success |
last operation was successful |
Failed |
last operation failed |
Running |
currently running |
Waiting |
waiting for something |
Stopped |
stopped processing |
Error |
an error occurred |
The diagram below shows the states and their related transitions:
Context:
The abstract Context class (and it's default BasicContext class) provides the mechanism for associating a Consumer Tier with a Service Tier. The Context is responsible for starting, configuring and running a solution that is built using the OpenPTK. The Context leverages many of the features that it inherits from the Component class.
A BasicContext reads configuration parameters from a Java properties file, initiates infrastructure processes (logging, debugging) starts the specified Service and processes Request/Response messages. Once started, the Context basically receives Requests from a Consumer, sends them to the Service, receives Responses from the Service and hands them back to the Consumer.
The Context has the ability of recording Timestamps. If enabled, the Context will record when a Request is received and when the Response is returned.
Since the Context deals with abstracted Subject data and their related attributes, the Context can be configured to sort the results of a Search request. This is an optional feature that might be needed for those Services that might not sort the results of Search operation.
It's possible to create a new Context (or extend the BasicContext) to support more robust capabilities like connection retries, HA functionality and load-balancing.
Request:
The Request class is an extension of the Component class. A Request object represents in "in-bound" provisioning operation. The Request object must contain a "type" setting. Valid types include:
Type |
Description |
RequestIF.CREATE |
Create a new subject. The Subject will contain a set of Properties and Attr objects that defined the attribute (names and values) and meta data that will be used during the create process. |
RequestIF.READ |
Read a single subject. The Subject's uniqueId is used to locate the information directly. The Subject will contain a List of attributes that should be returned as part of the read process. |
RequestIF.UPDATE |
Update a single subject. Like the CREATE Request, the Subject will contain a set of Properties and Attr objects that defined the attribute (names and values) that should be used during the update process. |
RequestIF.DELETE |
Delete a single subject. The Subject's uniqueId is used to identify the specific record that needs to be removed. |
RequestIF.SEARCH |
Search for one or more subjects. The Request contains a List of attributes that should be returned as part of the search process. The Request may also contain one or more Query objects which are used as filters to the search operation. |
RequestIF.PWD_RESET |
Reset a subjects password. The Subject's uniqueId is used to identify the specific record that needs to be reset. |
RequestIF.PWD_CHANGE |
Change a subjects password. The Subject's uniqueId is used to identify the specific record that needs to be changed. The Subject will also contain a Property that holds the new password that's to be used. |
The Request will also contain a Subject. The Subject is actually a Component object that contains information need to support the particular operation.
The illustration below is an example of a simple Request that will instruct the Context/Service to perform a Search operation:
Response:
The Response class is an extension of the Component class. A Response object represents the results of a provisioning operation. The returned Response object will contain important meta information about the provisioning operation:
Meta data |
Interface |
Description |
Error |
response.isError() |
Was there an error during the provisioning process. |
State |
response.getState() |
What is the state of the response, see the Component State table. The Response should be either Success or Failed |
Status |
response.getStatus() |
A String that describes the status of the response. This is set by the Service and/or Context. It should contain detailed error information. |
The Response object will contain successful provisioning operation data in one or more related Components. The components are accessible through the response.getResults() method which returns a List of Components. If configured, the Context will sort the results based on attributes defined in the properties file. The Response object will also contain the original Request object. The diagram below illustrates a Response object from a Search operation:
The Debugging package:
com.sun.idmkit.provision.debug
Debugger:
The Debugger provides a means to interrogate and dump information about Provision Toolkit objects. The Debugger objects knowns about the base Component class, the Context, Request and Response classes.
The Debugger is designed to assist the developer and operator. When the state of a Component is needed, simply pass-it to the Debugger, it will determine what it is, extract information from the object and send it to the defined Logging facility.
The Debugger is typically created in a Context where it can assist the Service, Request, Response and the Context.
if ( request.isDebug() ) debug(request, callerId);
The Debugger class writes plain ascii data to the Logger facility. A sample of the output is below:
Aug 15, 2006 2:53:07 PM com.sun.idmkit.provision.logging.AtomicLogger put
FINEST: DebugRequest, callerId=BasicContext::execute()
com.sun.idmkit.provision.common.Request
Metadata:
UniqueId=3583619
Category=request (3)
Description=Provision Request: Read
Sort=(not set)
Status=(not set)
State=Ready (2)
Error=false
Debug=true, Level=finest (4)
Type=Read (2)
Properties:
(no properties)
Items:
(no items)
Timestamps:
(no timestamps)
----- BEGIN: Subject -----
com.sun.idmkit.provision.common.Component
Metadata:
UniqueId=jhancock
Category=person (6)
Description=Component: userdetail
Sort=(not set)
Status=Created: Tue Aug 15 14:53:07 CDT 2006
State=Ready (2)
Error=false
Debug=true, Level=finest (4)
Properties:
(no properties)
Items:
person.attribute.firstname
person.attribute.lastname
person.attribute.title
person.attribute.fullname
person.attribute.email
person.attribute.phonework
person.attribute.organization
person.attribute.manager
Timestamps:
(no timestamps)
----- END: Subject -----
(No Conditions)
The Debugger will only interrogate those objects that have the isDebug value set to true.
DebugComponent:
The DebugComponent class knows how to extract and dump the common information for any class that is either a Component or extends Component. The information extracted includes:
Metadata:
- UniqueId
- Category
- Description
- Sort String
- Status
- State
- isError
- isDebug
- Debug Level
Properties:
Items:
Timestamps:
Subject (a Component)
DebugContext:
The DebugContext class knows how to extract and dump specific information about the Context object. If the Context's debug level is set to "4", then the Context's Service information will be added to the Logging service.
DebugRequest:
The DebugRequest class knows how extract and dump specific information about the Request object. The extra information includes:
- Request Type
- Subject object
- Condition object
DebugResponse:
The DebugResponse class knowns how to extract and dump specifc information about the Response object. The extra information includes:
- Original Request
- List of returned Components (Subjects)
The Logging Package:
org.openptk.provision.logging
INSERT LOGGIN ARCH DIAGRAM
The Logging package provides a facility for recording audit, timestamps and debugging information. The Logging uses the Java Logging facility. The OpenPTK currently offers two Logger implementations:
SimpleLogger |
This classes uses the standard Java logging.Logger package. Because of how the Logger and the OpenPTK are architected, multiple log files could be created. This by design to address concurrency issues with the actual log file. |
AtomicLogger |
This classes uses the standard Java logging.Logger package. It solves the multiple log file problem by "atomically" opening the log, writing the data and closing the log. Only one file is created. The side effect is performance may be a little slower. |
Attribute Rules:
When a Request is sent to the Service Tier, via the Context, the Service can contact a Model object to perform the derivation of attributes.
For example: The a Create Request contains a Subject with properties that define the subjects attributes:
Subject Properties: (attributes)
Name |
Value |
person.attribute.firstname |
John |
person.attribute.lastname |
Wayne |
person.attribute.title |
The Duke |
The Service can use a Model's Attributes and the Subject to obtain other required attributes such as UniqueId, Full Name and Email. Once the Model has been told what Attribute Rule (java class) to use for a give Attribute Name, the new attribute can be generated by providing the Model with the Subject information. The following Attribute Rules are available:
EmailAddress |
"john.wayne@company.com" |
FirstInitialLastName |
"jwayne" |
FirstNameSpaceLastName |
"John Wayne" |
Custom Attribute Rules can be created by implementing the AttributeIF interface.
The Service Package:
org.openptk.provision.service
The Service package contains an abstract class called Service. This class must be extended and implements the ServiceIF interface. This interface is what the Context uses to perform all of the back-end provisioning operations. The Service abstract class has implemented several "common" methods that will be needed by a Service that extends this class.
The Service class provides the following capabilities:
- getters / setters for connection information (host, port, user, passwd, etc)
- The execute() method to process Requests and return Responses
- Validates inbound Requests
- Initialization of attribute translation maps
- Bi-directional attribute translation method
When a Service is created (usually by the Context) it is given a set of Properties that contain Target specific information. This information can include connection data, meta data, operational data and attribute mapping data.
Provisioning Methods:
The Service's interface (ServiceIF) defines the methods that the actual Service must implement or can overload.
Method |
Type |
Description |
doCreate() |
implement |
Create a Subject |
doRead() |
implement |
Read a single Subject |
doUpdate() |
implement |
Update a single Subject |
doDelete() |
implement |
Delete a single Subject |
doSearch() |
implement |
Select one or more Subjects |
doPasswordChange() |
implement |
Change a Subjects Password |
doPasswordReset() |
implement |
Reset a Subjects Passoword |
startup() |
overload |
Called after Service is created |
shutdown() |
overload |
Called before Service is destroyed |
preprocess() |
overload |
Called before any "do" operation |
postprocess() |
overload |
Called after any "do" operation |
Attribute Translation:
The Provisioning Toolkit can be used to perform provisioning operations on different Target systems. Each Target system may (probably does) have a specific schema for defining a Subjects (Person) attributes. For example, SPML uses "gn" to define a "first name", while LDAP uses "givenname" for the "first name".
The OpenPTK uses an abstracted naming schema to define a Subjects attributes. The attribute names are abstracted so that the Consumer Tier of the OpenPTK only has to deal with a single set of attribute names.
The Service (specifically an implementation) MUST perform the translation of attributes from the OpenPTK Framework schema to a native schema before performing a given operation. Then, when the operation is complete, the Service implementation must translate the native schema attributes back to the OpenPTK Framework schema.
The attribute schema mapping is specified in a Properties file that is unique to a given service. Here is an example of an SPML schema mapping Properties file:
person.attribute.uniqueid=uid
person.attribute.firstname=gn
person.attribute.lastname=sn
person.attribute.title=title
person.attribute.fullname=cn
person.attribute.email=email
person.attribute.password=password
person.attribute.epassword=epassword
person.attribute.phonework=telephone
person.attribute.organization=organization
person.attribute.manager=manager
The abstract Service class has a method called translate() where you tell it which way to translate the provided Component, either Framework-to-Service or Service-to-Framework.
Service Tier:
The Service Tier is the "back-end" of the Open Provisioning Toolkit (OpenPTK) ... "where the rubber meets the road".
A Service is a Java class that performs Target specific provisioning operations using the Targets Java APIs. A given Service must extend the OpenPTK Framework's Service class and implement the ServiceIF interface.
See the "Service Package" section within the "Framework Tier" part of this document for details on the Service's capabilities.
INSERT IMAGE OF SERVICE TIER ARCHITECTURE
Service Provisioning Markup Language (SPML) Service:
This Service implementation is based on the Service Provisioning Markup Language 1.0 as defined by the OASIS Provisioning Services Technical Committee (PSTC).
The SPML Service leverages the following APIs to implement the Framework's provisioning operations:
Operation: |
SPML APIs: |
CREATE |
SpmlClient client = new SpmlClient();
AddRequest add = new AddRequest();
add.setIdentifier(...);
add.setAttributes(...);
AddResponse resp = (AddResponse) client.request(add);
|
READ |
SpmlClient client = new SpmlClient();
SearchRequest read = new SearchRequest();
Identifier ident = new Identifier();
ident.setId(...);
ident.setType(Identifier.TYPE_GUID);
read.setIdentifier(ident);
read.setAttributes(...);
SearchResponse resp = (SearchResponse) client.request(read);
|
UPDATE |
SpmlClient client = new SpmlClient();
ModifyRequest mod = new ModifyRequest();
mod.setIdentifier(...);
mod.setModifications(...);
ModifyResponse resp = (ModifyResponse) client.request(mod);
|
DELETE |
SpmlClient client = new SpmlClient();
DeleteRequest del = new DeleteRequest();
del.setIdentifier(...);
DeleteResponse resp = (DeleteResponse) client.request(del);
|
SEARCH |
SpmlClient client = new SpmlClient();
SearchRequest srch = new SearchRequest();
Filter filter = new Filter();
FilterTerm term = new FilterTerm();
srch.setAttributes(...);
filter.addTerm(term); // can have multiple terms
srch.setFilter(filter);
SearchResponse resp = (SearchResponse) client.request(srch);
|
PWD_RESET |
SpmlClient client = new SpmlClient();
ExtendedRequest ext = new ExtendedRequest();
ext.setOperationIdentifier("resetUserPassword");
ext.setAttribute("accountId",...);
ext.setAttribute("accounts","Lighthouse,...");
ExtendedResponse resp = (ExtendedResponse) client.request(ext);
|
PWD_CHANGE |
SpmlClient client = new SpmlClient();
ExtendedRequest ext = new ExtendedRequest();
ext.setOperationIdentifier("changeUserPassword");
ext.setAttribute("accountId",...);
ext.setAttribute("password",...);
ext.setAttribute("accounts","Lighthouse,...");
ExtendedResponse resp = (ExtendedResponse) client.request(ext);
|
| Note The PWD_RESET and PWD_CHANGE operations are implemented as ExtendedRequests. A SPML ExtendedRequest is an interface that allows specific products to leverage unique capabilities. The use of ExtendedRequests may not be portable between different vendor SPML products. This Service is based on the Sun Java System Identity Manager 6.0, 7.0, 8.0 product and its SPML 1.0 capabilities. |
Java Naming Directory Interface (JNDI) Service:
This Service implementation is based on the Java Naming and Directory Interface (JNDI) Service, part of the Java platform, providing applications based on Java technology with a unified interface to multiple naming and directory services.
The JNDI Service leverages the following APIs to implement the Framework's provisioning operations:
Operation: |
JNDI APIs: |
CREATE |
InitialLdapContext ldapCtx = new InitialLdapContext(...);
BasicAttributes ldapAttrs = new BasicAttributes();
for {
ldapAttrs.put(new BasicAttribute(...));
}
String entryDN = getEntryDN(request);
ldapCtx.createSubcontext(entryDN, ldapAttrs);
|
READ |
InitialLdapContext ldapCtx = new InitialLdapContext(...);
String baseDN = getBaseDN(request);
String searchStr = rdnKey + "=" + request.getSubject().getUniqueId();
List<String>attrNames = request.getSubject.getAttributeNames();
SearchControls searchCtls = new SearchControls(SUBTREE_SCOPE);
searchCtls.setReturningAttributes(attrNames);
NamingEnumeration ldapResults = ldapCtx.search(baseDN, searchStr, srchCtls);
List resultsList = getResults(ldapResults);
|
UPDATE |
InitialLdapContext ldapCtx = new InitialLdapContext(...);
BasicAttributes ldapAttrs = new BasicAttributes();
for {
ldapAttrs.put(new BasicAttribute(...));
}
String entryDN = getEntryDN(request);
ldapCtx.modifyAttributes(entryDN, 2, ldapAttrs);
|
DELETE |
InitialLdapContext ldapCtx = new InitialLdapContext(...);
String entryDN = getEntryDN(request);
ldapCtx.destroySubcontext(entryDN);
|
SEARCH |
InitialLdapContext ldapCtx = new InitialLdapContext(...);
String baseDN = getBaseDN(request);
String searchFiter = getLdapSearch(request);
List<String>attrNames = request.getSubject.getAttributeNames();
SearchControls searchCtls = new SearchControls(SUBTREE_SCOPE);
searchCtls.setReturningAttributes(attrNames);
NamingEnumeration ldapResults = ldapCtx.search(baseDN, searchFilter, srchCtls);
List resultsList = getResults(ldapResults);
|
PWD_RESET |
Not Implemented for JNDI Service |
PWD_CHANGE |
Not Implemented for JNDI Service |
Java DataBase Connectivity (JDBC) Service:
This Service implementation is based on the Java DataBase Connective (JDBC) Service, part of the Java platform, providing applications based on Java technology with a unified interface to database services.
The JDBC Service leverages the following APIs to implement the Framework's provisioning operations:
Operation: |
JDBC APIs: |
CREATE |
Connection conn = DriverManager.getConnection(url, uid, password);
Statement stmt = conn.createStatement();
String sql = "INSERT INTO " + request.getTableName() +
request.getAttrNames() +
" VALUES " + request.getAttrValues()
stmt.executeUpdate(sql);
|
READ |
Connection conn = DriverManager.getConnection(url, uid, password);
Statement stmt = conn.createStatement();
String sql = "SELECT " + request.getAttrNames() +
" FROM " + request.getTableName() +
" WHERE " + request.getQuery();
ResultSet rs = stmt.executeQuery(sql);
|
UPDATE |
Connection conn = DriverManager.getConnection(url, uid, password);
Statement stmt = conn.createStatement();
String sql = "UPDATE " + request.getTableName() +
" SET " + request.getTableMods() +
" WHERE " + request.getQuery();
stmt.executeUpdate(sql);
|
DELETE |
Connection conn = DriverManager.getConnection(url, uid, password);
Statement stmt = conn.createStatement();
String sql = "DELETE FROM " + request.getTableName() +
" WHERE " + request.getQuery();
stmt.executeUpdate(sql);
|
SEARCH |
Connection conn = DriverManager.getConnection(url, uid, password);
Statement stmt = conn.createStatement();
String sql = "SELECT " + request.getAttrNames() +
" FROM " + request.getTableName() +
" WHERE " + request.getQuery();
ResultSet rs = stmt.executeQuery(sql);
|
PWD_RESET |
Not Implemented for JDBC Service |
PWD_CHANGE |
Not Implemented for JDBC Service |
Appendix: Forgotten Password
When a Consumer-Tier application (UML / Portlets / Samples) initiates the forgotten password process, the Framework makes a single call to the Service and it stores both the questions and answers internally. When the user responds to the questions, the APIs compare the users input to the answers that are internally stored.