Saturday, July 26, 2008

 

Deleting a User with IDXML

Certain actions (such as creating or removing an LDAP entry) are only available via OAM's 'workflow' engine. A freshly installed OAM system has no workflows configured, thus, no immediate mechanism to affect such actions.

To the newly initiated, discovering the create workflow mechanisms are relatively straightforward. But the delete, however, tends to throw people for a loop at first.

The trick is to create a 'Deactivate User Workflow'. Exactly what this workflow does is up the user building the workflow. You'll find, following the definition of the initial step, three similar action choices:

If your goal is truly to whack the account, choose delete. Otherwise, a choice of disable will set the user account ObUserAccountControl flag to DEACTIVATED (with no human interaction required). By default, the Identity System ignores DEACTIVATED accounts in the user searchbase. The deactivate action accomplishes the same thing but it requires a human participant to actually push the button to confirm the action.

Lastly, if you want to access this 'Delete User Workflow' from IDXML you just need to keep in mind that it is a workflow you are calling. Pay close attention to:
Here is a complete request for calling a Deactivate User Workflow:


<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas-xmlsoap.org/soap/envelope/" xmlns:oblix="http://www.oblix.com">
<SOAP-ENV:Body>
<oblix:authentication type="basic">
<oblix:login>admin</oblix:login>
<oblix:password>test1234</oblix:password>
</oblix:authentication>
<oblix:request application="userservcenter" function="workflowDeactivateUserSave" version="NPWSDL1.0">
<oblix:params>
<oblix:ObWorkflowName>obworkflowid=c60491a5ca0a45668fff08da2f1072d2,obcontainerId=workflowDefinitions,OU=Oblix,OU=apps,DC=company,DC=com</oblix:ObWorkflowName>
<oblix:uid>UID=372af3c1-0c7e-428d-a80a-fae632211489,OU=people,DC=company,DC=com</oblix:uid>
<oblix:noOfFields>2</oblix:noOfFields>
<AttributeParams xmlns="http://www.oblix.com/">
<GenericAttribute>
<AttrName>cn</AttrName>
<AttrNewValue>test</AttrNewValue>
<AttrOperation>REPLACE_ALL</AttrOperation>
</GenericAttribute>
<GenericAttribute>
<AttrName>userStatus</AttrName>
<AttrNewValue>delete</AttrNewValue>
<AttrOperation>REPLACE_ALL</AttrOperation>
</GenericAttribute>
</AttributeParams>
</oblix:params>
</oblix:request>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>


Labels:


Tuesday, July 22, 2008

 

OAM Identity XML (IDXML) via XMLHttpRequest

It makes sense that the ideal HTTP Client for IDXML processing is the authenticated user's browser. After all, it already has the ObSSOCookie.

JQuery is the Javascript library of choice for all my client work lately. You can see why in the following example of processing an IDXML request via Javascript straight from the client. The use cases for this capability are endless.

This is the proverbial 'tip of the iceberg' in utilizing OAM Identity in a modern web development context. The end result: Perfectable user experiences based on data and services made available and secured through OAM's web based configuration tools. It's a powerful combination.

Lets take a simple create user workflow request and turn out a simple Javascript templating function to build the string for us:

getSoap = function(data){
var dat = [];
dat[dat.length] = '<?xml version="1.0" encoding="UTF-8"?>';
dat[dat.length] = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas-xmlsoap.org/soap/envelope/" xmlns:oblix="http://www.oblix.com">';
dat[dat.length] = '<SOAP-ENV:Body>';
dat[dat.length] = '<oblix:request function="workflowSaveCreateProfile" version="NPWSDL1.0">';
dat[dat.length] = '<oblix:params>';
dat[dat.length] = '<oblix:ObWorkflowName>obworkflowid=672fcf2e9c5946a8b5b225b349acd46b,obcontainerId=workflowDefinitions,OU=Oblix,OU=apps,DC=company,DC=com</oblix:ObWorkflowName>';
dat[dat.length] = '<oblix:ObDomainName>OU=people,DC=company,DC=com</oblix:ObDomainName>';
dat[dat.length] = '<oblix:noOfFields>5</oblix:noOfFields>';
dat[dat.length] = '<AttributeParams xmlns="http://www.oblix.com/">';
dat[dat.length] = '<GenericAttribute>';
dat[dat.length] = '<AttrName>uid</AttrName>';
dat[dat.length] = '<AttrNewValue>'+data.uid+'</AttrNewValue>';
dat[dat.length] = '<AttrOperation>ADD</AttrOperation>';
dat[dat.length] = '</GenericAttribute>';
dat[dat.length] = '<GenericAttribute>';
dat[dat.length] = '<AttrName>cn</AttrName>';
dat[dat.length] = '<AttrNewValue>'+data.cn+'</AttrNewValue>';
dat[dat.length] = '<AttrOperation>ADD</AttrOperation>';
dat[dat.length] = '</GenericAttribute>';
dat[dat.length] = '<GenericAttribute>';
dat[dat.length] = '<AttrName>mail</AttrName>';
dat[dat.length] = '<AttrNewValue>'+data.mail+'</AttrNewValue>';
dat[dat.length] = '<AttrOperation>ADD</AttrOperation>';
dat[dat.length] = '</GenericAttribute>';
dat[dat.length] = '<GenericAttribute>';
dat[dat.length] = '<AttrName>givenName</AttrName>';
dat[dat.length] = '<AttrNewValue>'+data.givenName+'</AttrNewValue>';
dat[dat.length] = '<AttrOperation>ADD</AttrOperation>';
dat[dat.length] = '</GenericAttribute>';
dat[dat.length] = '<GenericAttribute>';
dat[dat.length] = '<AttrName>sn</AttrName>';
dat[dat.length] = '<AttrNewValue>'+data.sn+'</AttrNewValue>';
dat[dat.length] = '<AttrOperation>ADD</AttrOperation>';
dat[dat.length] = '</GenericAttribute>';
dat[dat.length] = '</AttributeParams>';
dat[dat.length] = '<oblix:obactorcomment>IDXML from browser via Javascrip</oblix:obactorcomment>';
dat[dat.length] = '</oblix:params>';
dat[dat.length] = '</oblix:request>';
dat[dat.length] = '</SOAP-ENV:Body>';
dat[dat.length] = '</SOAP-ENV:Envelope>';

return dat.join("");
};


Then, if we prep a little data object with values (presumably pulled from the user interface):


var userdata = {
uid:"marmil",
cn:"Mark Miller",
mail:"mark[at]nulli.com",
givenName:"Mark",
sn:"Miller"
};


I can call my template and consider my soap envelope ready to go:


var createUserSoapRequest = getSoap(userdata);


All over but the sending (and response handling):


// process the request
$.ajax({
type: "POST",
dataType:'xml',
url: "/identity/oblix/apps/userservcenter/bin/userservcenter.cgi",
data: createUserSoapRequest,
contentType:"text/xml",
processData:false,
success: function(idxmlResponse){
// crude
alert(idxmlResponse);

// better
$("ObConfirmation",idxmlResponse).find("ObValue").each(function(i,o){
alert($(o).text());
});

// in the real world, employ dom trickery to keep the user oriented...
}
});



Cool, no?

Labels:


 

OAM Search Results Virtual Attribute

What if you want to include a virtual attribute in your search results that is derived form another attribute? Just create the attribute in an outbound mapper flow and add it to the search results and it should show up as expected - right? Well, maybe it will and maybe it won't; if the attribute(s) the derived value is based on is/are in the search results too then it will show up as anticipated. However, if they are not there then it won't show up as expected.

The solution is to use the OVD addReturnAttribute delivered mapper function on the reciprocal inbound request with the required source attributes. This will allow the outbound mapper to have the required data to complete the derived attribute and enable the OAM search result configuration to exist without the source attributes.

Labels: , ,


 

One Bad Mapper Can Spoil the Whole Bunch (if you're not careful)

Creating a mapping file for OVD to use on inbound and/or outbound LDAP transactions can sometimes be tricky to get absolutely correct the first time. Invariably, the message
Could not complete mapping
is bound to show up at least once when you are trying something new.

When a mapping file is broken it can cause a variety of problems, but most notably if your adapters for authentication are using other unrelated mappers it can cause them to fail, resulting in failed authentication. So for instance if you are working on a mapper for one object you could prevent other users from authenticating. This pitfall can be easily avoided, however, using the OVD Filters to Exclude and Filters to Include fields on the routing tab of the adapters tab in OVD Manager. For instance by exluding (objectclass=inetorgperson) from an adapter that presents site data you can prevent an authentication search request from even attempting the adapter, thus insulating you and other development users from such a problem.

However, what if you cannot authenticate to the OVD Manager console to correct a broken mapper or add a routing filter to an adapter? I had one case where I could not authenticate even as cn=admin do the OVD Manager becuase of a broken adapter. The solution to this is simple; just remove the compiled mapper jar file from the OVD Server directory. You can do so by following these steps:
  1. stop ovd
  2. remove bad mapper ($VDE_DIR/mappings/jars/offendingMappingFile.jar)
  3. start ovd
  4. log into the OVD Manager and fix the source of the problem

Labels: , ,


Thursday, July 03, 2008

 

Error: Look up of symbol - ObInitEventAPI failed

If you ever receive an error like this when trying to configure an identity system .NET based PPP event, check the action; chances are it is set to lib instead of managedlib.

"Event API call for the event returned STATUS_PPP_ABORT" Error^base\obport.cpp:845: Error: Look up of symbol - ObInitEventAPI failed - The specified procedure could not be found.%0d%0a.

Labels: ,


This page is powered by Blogger. Isn't yours?