Tuesday, April 27, 2010

Web Services with Novell IDM

So I have a pretty unique request.  A customer asked me to integrate IDM with a system that doesn't have a standard interface that I could use to integrate.  It did, however, have an API that we could use to create our own interface.  The customers programmer decided that the easiest way to implement this would be to setup a web service for me to call. 

While initially, I thought this was a candidate for the SOAP driver, I realized that this driver is overkill for the simplicity of this implementation.  This is a sample of how we would be creating a user in the system from IDM:

http://www.server.com/addUser?username=testuser&fname=test&lname=user&password=Passw0rd&othreattribute=other1&....

SOAP is complete overkill, I just need to construct a simlpe URL and call a linux wget on that URL.  The resulting status message would be returned instead of a typical HTML page when the API code processed the request.

I did some research and decided the easiest way to implement this would be to use ECMAScript to call some custom code that would very easily call my URL and return the result for me.  I would shove the result into a local variable in policy then jam that sucker into an attribute on the user object in eDirectory.  Seems like a very simple implementation, here is how I was able to do it.

Below is the ECMAScript for the function that I wrote.  Its a simple function, urlGet. You pass it the URL and it returns whatever is returned when a GET operation is performed on that URL.

importClass(java.net.URL);
importClass(java.io.InputStreamReader);
importClass(java.lang.StringBuilder);

function urlGet(urlString) {
try {
var url = new java.net.URL(String(urlString));
var stream = url.openStream();
var reader = new java.io.InputStreamReader(stream, "UTF-8");
var sb = new java.lang.StringBuilder();
var c;
while ((c = reader.read()) != -1) {
sb.append(String.fromCharCode(c));
}
return sb.toString();
} catch(e) {
return e.toString();
}
}

Now, we post that ECMAScript and use it in our driver with the following.  It will use the URL that is stored in the Local Variable myURL and return the results back to lv.URLResult.

            <do-set-local-variable name="lv.URLResult" scope="policy">
                <arg-string>
                    <token-xpath expression="es:urlGet($myURL)"/>
                </arg-string>
            </do-set-local-variable>

Program some logic to store the result in some sort of status attribute, then business logic to construct the correct URL and your can very easily IDM enable a web service based system.

4 comments:

  1. I also encounter the similar problem,
    Could you tell me whar driver you use?

    My E-Mail is davidhsu87@gmail.com

    Thanks

    ReplyDelete
  2. That ECMAScript can be implemented in any driver. If this is the only call you need to make, I would suggest using a Null Services or Loopback driver. Add in the business logic, then call the ECMAScript to hit your remote web URL.

    Please keep in mind, this is not the same as SOAP web services. For those, you will want to leverage the SOAP driver.

    ReplyDelete
  3. I've also figured out how to do a Post, if you have a Document as a string variable you can pass that in as urlPost:

    importClass(java.net.URL);
    importClass(java.net.Proxy);
    importClass(java.net.HttpURLConnection);
    importClass(java.net.InetSocketAddress);
    importClass(java.io.InputStreamReader);
    importClass(java.io.OutputStream);
    importClass(java.io.OutputStreamWriter);
    importClass(java.io.PrintStream);
    importClass(java.lang.StringBuilder);

    function urlPost(urlString,inputvar) {
    try {
    var url = new java.net.URL(String(urlString));
    var test = urlString;

    // If you need a Proxy Server to send your HTTP Request
    // var addr = new InetSocketAddress("127.0.0.1", 8080);
    // var proxy = new Proxy(Proxy.Type.HTTP, addr);
    // var conn = url.openConnection(proxy);
    // Or Direct
    var conn = url.openConnection();

    conn.setDoOutput(true);
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Content-Type", "text/xml");
    var osw = new OutputStreamWriter(conn.getOutputStream());
    osw.write(inputvar);
    osw.flush();
    var reader = new java.io.InputStreamReader(conn.getInputStream(), "UTF-8");
    var sb = new java.lang.StringBuilder();
    var c;
    while ((c = reader.read()) != -1) {
    sb.append(String.fromCharCode(c));
    }
    return sb.toString();
    } catch(e) {
    return e.toString();
    }
    }

    ReplyDelete
  4. Your example of POST did not work for me

    ReplyDelete