Monday, 29 September 2014

#ShellShock - Bash broke my VMware

So, to avoid impact by the infamous #ShellShock breach, I removed /bin/bash and, inadvertently, broke VMware Fusion.

This is what I see: -


VMware Fusion is damaged and could not be repaired. Please move the VMware Fusion application to the Trash and reinstall VMware Fusion.

Solution ? Don't remove /bin/bash :-)

Friday, 26 September 2014

IBM BPM 8.5.0 - Updating REST Endpoints programmatically

Now I've been seeking a way to achieve this for a wee while now, and finally here it is, thanks in large part to the excellent IBM BPM Community within IBM, many of whom came to my rescue.

In essence, I want to be able to update the various REST endpoints within the IBM BPM WAS applications, when I add in IBM HTTP Server ( either co-located or separate ) and HTTP load balancing. This allows the RESTful services to be rendered via the web tier, rather than going directly to the WAS Web Container.

This IS possible via the Integrated Solutions Console (ISC) GUI, but I was struggling to find a CLI way to achieve it.

Thanks to my extended network, this is what worked for me: -

Start wsadmin client

/opt/ibm/WebSphereProfiles/Dmgr01/bin/wsadmin.sh -lang jython -host `hostname` -port 8879  -user wasadmin -password passw0rd

Update Rest Services Gateway - One WAR - rest.gateway.war

AdminTask.updateRESTServiceProvider(['-clusterName','AppCluster','-appName', 'REST Services Gateway_AppCluster', '-webModuleName', 'rest.gateway.war', '-hostName', 'bpm8501.uk.ibm.com', '-port', '8443' , '-transportType', 'https://'])

Update TeamWorks - one RESTy WARs - bpmrest.war

AdminTask.updateRESTServiceProvider(['-clusterName','AppCluster','-appName', 'IBM_BPM_Teamworks_AppCluster', '-webModuleName', 'bpmrest.war', '-hostName', 'bpm8501.uk.ibm.com', '-port', '8443' , '-transportType', 'https://'])

Update BPE Container - one RESTy WAR - bfmrestapi.war

AdminTask.updateRESTServiceProvider(['-clusterName','AppCluster','-appName', 'BPEContainer_AppCluster', '-webModuleName', 'bfmrestapi.war', '-hostName', 'bpm8501.uk.ibm.com', '-port', '8443' , '-transportType', 'https://'])

Update Task Container - one RESTy WAR - taskrestapi.war

AdminTask.updateRESTServiceProvider(['-clusterName','AppCluster','-appName', 'TaskContainer_AppCluster', '-webModuleName', 'taskrestapi.war', '-hostName', 'bpm8501.uk.ibm.com', '-port', '8443' , '-transportType', 'https://'])

Save and Synchronise

AdminConfig.save()
AdminNodeManagement.syncActiveNodes()
quit

I validated that I had the correct number of RESTy WARs: -

cat /opt/ibm/WebSphereProfiles/Dmgr01/config/cells/PSCell1/config-rest.xml | grep 8443

<webModules xmi:id="WBIRestWebModule_1411489980815" name="rest.gateway.war" applicationName="REST Services Gateway_AppCluster" contextRoot="/rest" transportType="https://"; hostName="bpm8501.uk.ibm.com" port="8443">

<webModules xmi:id="WBIRestWebModule_1411489982410" name="bpmrest.war" applicationName="IBM_BPM_Teamworks_AppCluster" contextRoot="/rest/bpm/wle" transportType="https://"; hostName="bpm8501.uk.ibm.com" port="8443">

<webModules xmi:id="WBIRestWebModule_1411489983613" name="bfmrestapi.war" applicationName="BPEContainer_AppCluster" contextRoot="/rest/bpm/bfm" transportType="https://"; hostName="bpm8501.uk.ibm.com" port="8443">

<webModules xmi:id="WBIRestWebModule_1411489983637" name="taskrestapi.war" applicationName="TaskContainer_AppCluster" contextRoot="/rest/bpm/htm" transportType="https://"; hostName="bpm8501.uk.ibm.com" port="8443">

cat /opt/ibm/WebSphereProfiles/Dmgr01/config/cells/PSCell1/config-rest.xml | grep ".war"

<webModules xmi:id="WBIRestWebModule_1411489449181" name="rest.gateway.war" applicationName="REST Services Gateway Dmgr" contextRoot="/rest_dmgr" transportType="https://"; hostName="bpm8501.uk.ibm.com" port="9043">

<webModules xmi:id="WBIRestWebModule_1411489980815" name="rest.gateway.war" applicationName="REST Services Gateway_AppCluster" contextRoot="/rest" transportType="https://"; hostName="bpm8501.uk.ibm.com" port="8443">

<endpoints xmi:id="WBIRestEndpoint_1411489980822" id="6260563d-e009-499d-9d00-1c56cbd062e2" name="Store and forward" description="WBI Store and Forward REST API" type="{com.ibm.bpm}Qualifier" typeDisplayName="SCA Qualifier" version="7.0.0.0" publicEndpoint="true" providerEndpointID="StoreAndForward" relativeURL="/bpm/qos/storeandforward"/>

<webModules xmi:id="WBIRestWebModule_1411489982410" name="bpmrest.war" applicationName="IBM_BPM_Teamworks_AppCluster" contextRoot="/rest/bpm/wle" transportType="https://"; hostName="bpm8501.uk.ibm.com" port="8443">

<webModules xmi:id="WBIRestWebModule_1411489983613" name="bfmrestapi.war" applicationName="BPEContainer_AppCluster" contextRoot="/rest/bpm/bfm" transportType="https://"; hostName="bpm8501.uk.ibm.com" port="8443">

<webModules xmi:id="WBIRestWebModule_1411489983637" name="taskrestapi.war" applicationName="TaskContainer_AppCluster" contextRoot="/rest/bpm/htm" transportType="https://"; hostName="bpm8501.uk.ibm.com" port="8443">

PS This also works for IBM Business Monitor 8.0.1.2, running on WAS 8.0.0.8: -

/opt/ibm/WebSphereProfiles/Dmgr01/bin/wsadmin.sh -lang jython -user wasadmin -password passw0rd
AdminTask.updateRESTServiceProvider(['-clusterName','WebCluster','-appName', 'REST Services Gateway_WebCluster', '-webModuleName', 'rest.gateway.war', '-hostName', 'bam8012.uk.ibm.com., '-port', '8443' , '-transportType', 'https://'])
AdminConfig.save()
AdminNodeManagement.syncActiveNodes()
quit 


*UPDATE* As if by magic, I've just found a page in the IBM BPM documentation that says much the same: -

Updating context roots in an existing network deployment environment

as well as this old-but-good Technote: -

Customize System REST Services Context Root: /rest

Time for Bash - No, not #ShellShock

So I have a backup script that I use to backup certain folders on my Mac to an external USB drive: -

#! /bin/bash

# now=$(date +"%d_%m_%Y" +"_" +"%h:%m")
now=`date +%d-%m-%Y-%H-%M-%S`

tar cvzf notes_$now.tar.gz ~/Library/Application\ Support/IBM\ Notes\ Data/*
tar cvzf docs_$now.tar.gz ~/Documents/Docs.ISSW/*
tar cvzf customers_$now.tar.gz ~/Documents/Customers.ISSW/*
tar cvzf personal_$now.tar.gz ~/Documents/Personal/*
tar cvzf itunes_$now.tar.gz ~/Music/
tar cvzf pictures_$now.tar.gz ~/Pictures/


This is one of many backups, including TimeMachine, Synology NAS and SuperDuper. One can never have TOO many backups ;-)

My script calculates the current date/time and appends it to the filename: -

now=$(date +"%d_%m_%Y" +"_" +"%h:%m")

For some reason, that's stopped working recently - not sure precisely when but ...

This is what I now see: -

date: illegal time format
usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ... 
            [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]

A quick Google search later ( Adding date and time to file name ), I've changed the script to this: -

now=`date +%d-%m-%Y-%H-%M-%S`

and it works.

This is what I now get: -

notes_26-09-2014-15-56-38.tar.gz
docs_26-09-2014-15-56-38.tar.gz


etc.

WebSphere Application Server - JVM Performance

Pulling together some performance materials relating to IBM BPM, including this IBM Redbook: -


I also referenced a number of related articles: -




looking at aspects of Garbage Collection, including generational GC: -

Tuning generational GC

When the options are added, you will need to save and synchronize the changes before restarting the application server to put the changes in effect.

When tuning for generational garbage collection, the simplest approach is to treat the nursery space as a new Java heap area, in addition to the Java heap area used in the non-generational case. The Java heap for the non-generational case therefore becomes the tenured heap.

This approach is conservative: the expectation is that the occupancy of the tenured heap will drop as a result of introducing the nursery, but it provides a safe starting point, especially in the case of a migration from a non-generational policy. When the occupancy of the tenure heap after global (full) collections can be monitored, the size can then be adjusted as described earlier:

• -Xmn<size> sets the initial and maximum size of the nursery, effectively setting both -Xmns and -Xmnx.
• -Xmns<size> sets the initial size of the nursery to the specified value.
• -Xmnx<size> sets the maximum size of the nursery to the specified value.

The size of the nursery heap should be fixed, and as a result only one of these options, -Xmn is required. Therefore, you only need to understand how to correctly size the nursery heap.

Tuesday, 23 September 2014

IBM Integration Bus and the WebSphere Application Server (WAS) Plugin

So I am following this rather excellent developerWorks article: -


WebSphere Message Broker V8 lets you generate a configuration file for the WebSphere Plug-in or Apache mod_proxy modules, which are used by IBM HTTP Server and Apache HTTP Server respectively to enable HTTP load balancing. Part 1 of this two-part series shows you how to configure load balancing for WebSphere Message Broker HTTP traffic using WebSphere Plug-in and IBM HTTP Server. The article shows you how to use WebSphere Message Broker Java APIs and the WebSphere Message Broker Explorer to generate a WebSphere Plug-in configuration for IBM HTTP Server.

This includes some sample code that allows one to generate a plugin file for the WebSphere Application Server (WAS) Plugin.

This Java code makes use of the WebSphere MQ and IBM Integration Bus Java APIs, such as com.ibm.broker.config.proxy.BrokerConnectionParameters.

In order to compile the code, I created a new Java project in Eclipse (Kepler) called PluginGeneration, into which I placed the three source files: -

com.ibm.broker.load.plugin.GeneratePlugin
com.ibm.broker.load.plugin.WritePluginFile
com.ibm.broker.load.plugin.BrokerConnectionDetails

( the example source is in the article, including a downloadable ZIP ).

However, in order to compile the code, I needed to add a single IIB JAR file to my Eclipse build path: -

-rwxr-xr-x 1 wmbadmin mqbrkrs 12210797 Jun 19 19:21 /opt/ibm/mqsi/9.0.0.2/classes/ConfigManagerProxy.jar


Once I'd created the project, with the three classes, I used Eclipse to export it as a Runnable JAR file with the main method of the GeneratePlugin class set as the Launch configuration: -


I was then able to execute the JAR: -

java -jar PluginGeneration.jar 

=========================================================================================
*****************************************************************************************
*******************WebSphere Message Broker Plugin Generation Tool***********************
*****************************************************************************************
=========================================================================================

Do you want to add Broker Connection Details ? (y/n) = y

*****************************************************************************************

Please Enter the Broker Connection Details ( Hostname, QMName , QMPort )

Enter the Broker Hostname                            = bam8012.uk.ibm.com

Enter the Queue Manager Name                         = DAVEHAY

Enter the Queue Manager Listener Port Number         = 1414

Sadly, at that point, I hit this exception: -

Exception in thread "main" java.lang.NoClassDefFoundError: com.ibm.mq.MQException
at java.lang.J9VMInternals.verifyImpl(Native Method)
at java.lang.J9VMInternals.verify(J9VMInternals.java:94)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:171)
at com.ibm.broker.config.proxy.MQBrokerConnectionParameters.getSender(MQBrokerConnectionParameters.java:574)
at com.ibm.broker.config.proxy.BrokerProxy.<init>(BrokerProxy.java:322)
at com.ibm.broker.config.proxy.BrokerProxy.getInstance(BrokerProxy.java:863)
at com.ibm.broker.load.plugin.GeneratePlugin.main(GeneratePlugin.java:100)
Caused by: java.lang.ClassNotFoundException: com.ibm.mq.MQException
at java.net.URLClassLoader.findClass(URLClassLoader.java:599)
at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:760)
at java.lang.ClassLoader.loadClass(ClassLoader.java:728)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:325)
at java.lang.ClassLoader.loadClass(ClassLoader.java:707)
... 7 more

This led me to this IBM Technote: -


...
Why was the Java™ MQException Class moved to the com.ibm.mq.jmqi.jar file in WebSphere MQ V7.0?
...
The move of the MQException class to the new com.ibm.mq.jmqi.jar was as a result of significant re-engineering that was implemented across the MQ classes for Java and the MQ classes for JMS. The JMS classes (com.ibm.mq.jms.jar) and Java classes (com.ibm.mq.jar) are now independent and stand as peers, therefore the MQException Class was moved to a common JAR file that can be used by either the Java and JMS libraries.
...

Sadly, I've not yet come up with a perfect solution to this :-(

The issue, and the IBM Technote, implied that I needed to add one or more JARs to the Java class path, which I tried as follows: -

java -cp /opt/ibm/mqm/java/lib/com.ibm.mq.headers.jar:/opt/ibm/mqm/java/lib/com.ibm.mq.jar:/opt/ibm/mqm/java/lib/com.ibm.mq.jmqi.jar -jar /mnt/hgfs/Downloads/PluginGeneration.jar 

but to no avail.

I even tried adding in the additional IIB JAR: -

java -cp /opt/ibm/mqm/java/lib/com.ibm.mq.headers.jar:/opt/ibm/mqm/java/lib/com.ibm.mq.jar:/opt/ibm/mqm/java/lib/com.ibm.mq.jmqi.jar:/opt/ibm/mqsi/9.0.0.2/classes/ConfigManagerProxy.jar -jar /mnt/hgfs/Downloads/PluginGeneration.jar 

but again to no avail.

In the end, I found that the "optimum" solution was to include the four JARs: -

com.ibm.mq.headers.jar
com.ibm.mq.jar
com.ibm.mq.jmqi.jar
ConfigManagerProxy.jar

in the Build Path: -


AND also inside the exported JAR: -


which now allows me to successfully generate the WAS Plugin configuration: -

java -jar PluginGeneration.jar

=========================================================================================
*****************************************************************************************
*******************WebSphere Message Broker Plugin Generation Tool***********************
*****************************************************************************************
=========================================================================================

Do you want to add Broker Connection Details ? (y/n) = y

*****************************************************************************************

Please Enter the Broker Connection Details ( Hostname, QMName , QMPort )

Enter the Broker Hostname                            = bam8012.uk.ibm.com

Enter the Queue Manager Name                         = DAVEHAY

Enter the Queue Manager Listener Port Number         = 1414

Broker HTTP Service Details for this Broker Connection
Broker,HTTP/HTTPS,Port,URL,Execution Groups....

Do you want to add Broker Connection Details ? (y/n) = n

*****************************************************************************************

Enter the file name for Plugin                       = plugin-cfg.xml

Enter the location of file                           = /tmp

=========================================================================================
*****************************************************************************************
*********************Congratulation Plugin Generated Successfully************************
**************************Exiting Plugin Generation Tool*********************************
*****************************************************************************************
=========================================================================================


cat /tmp/plugin-cfg.xml 

<?xml version="1.0" encoding="UTF-8"?><Config>
    <!--PLUGININSTALLROOT MUST BE UNCOMMENTED FOR SSL-->
    <!--Property Name="PluginInstallRoot" Value="SET ME TO YOUR WEBSPHERE PLUGINS DIRECTORY"/-->
    <VirtualHostGroup Name="default_host">
        <VirtualHost Name="*:80"/>
    </VirtualHostGroup>



Still not sure why I need to have the WMQ/IIB JARs on build path AND exported within the JAR, but it works :-)

PS For the record, I did try executing the JAR like this: -

java -cp /opt/ibm/mqm/java/lib/com.ibm.mq.headers.jar:/opt/ibm/mqm/java/lib/com.ibm.mq.jar:/opt/ibm/mqm/java/lib/com.ibm.mq.jmqi.jar:/opt/ibm/mqsi/9.0.0.2/classes/ConfigManagerProxy.jar -jar PluginGeneration.jar

but that didn't end well either: -

Exception in thread "main" java.lang.NoClassDefFoundError: com.ibm.broker.config.proxy.ConfigManagerProxyLoggedException
at java.lang.J9VMInternals.verifyImpl(Native Method)
at java.lang.J9VMInternals.verify(J9VMInternals.java:94)
at java.lang.J9VMInternals.prepare(J9VMInternals.java:516)
at java.lang.Class.getMethod(Class.java:964)
at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:506)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:498)
Caused by: java.lang.ClassNotFoundException: com.ibm.broker.config.proxy.ConfigManagerProxyLoggedException
at java.net.URLClassLoader.findClass(URLClassLoader.java:599)
at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:760)
at java.lang.ClassLoader.loadClass(ClassLoader.java:728)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:325)
at java.lang.ClassLoader.loadClass(ClassLoader.java:707)
... 6 more



Finally, it's worth noting that I'm running the JAR as a user that's configured for BOTH WMQ and IIB: -

...
. /opt/ibm/mqm/bin/setmqenv -s -k

source /opt/ibm/mqsi/9.0.0.2/bin/mqsiprofile

...

with the following class path: -

/opt/ibm/mqsi/9.0.0.2/messages:/opt/ibm/mqsi/9.0.0.2/classes:/opt/ibm/mqsi/9.0.0.2/classes/ConfigManagerProxy.jar:/opt/ibm/mqsi/9.0.0.2/classes/brokerutil.jar:/opt/ibm/mqm/java/lib/com.ibm.mq.jar:/opt/ibm/mqm/java/lib/com.ibm.mqjms.jar:/opt/ibm/mqm/samp/wmqjava/samples:/opt/ibm/mqm/samp/jms/samples:/var/mqsi/common/wsrr



Monday, 22 September 2014

IBM HTTP Server / IBM Global Security Toolkit - Commanding the line ...

One of my colleagues was looking for inspiration, without too much perspiration, in order to create an SSL/TLS Certificate Service Request (CSR) using IBM HTTP Server and the Global Security Toolkit (GSK).

He was hoping to use the GUI tool, IKeyMan, but I tried very hard to persuade him that GUIs are for WIMPs, and that the command-line tool, gskcapicmd is the way to go ( whilst IHS also has ikeycmd, that relies upon a Java Runtime Environment, which may not always be available, especially on a production IHS server ).

Specifically, he wanted to set the Subject Alternate Name (SAN).

subjectAltName (SAN) is an extension to X.509 that allows various values to be associated with a security certificate.[1] These values are called "Subject Alternative Names", or SANs. Names include:[2]

• e-mail addresses
• IP addresses
• URIs
• DNS names (Otherwise often given as a Common Name RDN within the Subject)
• directory names (alternative Distinguished Names to that given in the Subject)
• other names, given as a General Name: an registered Object identifier followed by a value

This is easily done via the ikeyman GUI: -


and my colleague wanted to know how to achieve the same using gskcapicmd.

Here's my conclusion: -

/opt/IBM/HTTPServer/bin/gskcapicmd -certreq -create -db /opt/IBM/HTTPServer/ssl/keystore.kdb -pw passw0rd -label foobar -dn "cn=www.foobar.ibm.com" -size 2048 -file /tmp/foobar.csr -san_dnsname "www.foobar.ibm.com" -san_emailaddr "admin@us.ibm.com" -san_ipaddr "192.168.1.221"

This results in a nice little file: -

-rw-r--r--   1 wasadmin mqm        1009 Sep 22 15:44 foobar.csr

-----BEGIN NEW CERTIFICATE REQUEST-----
MIICqjCCAZICAQAwHTEbMBkGA1UEAxMSd3d3LmZvb2Jhci5pYm0uY29tMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr5hUIlJdYS9b+cWOCow56g1g2Wt
sfL0OsFWtXyjPjFBDgVxFhKgXwdti9qsnb6nmb0zJMXa4s09PBQpCtTVl0p9YlAL
JZZS9kCfg8W1/LGMcud5GpjJQ8F0Jxkt7CC32YXaDIN1FfgCkjwFafb8RoJx1u2S
xDZMgOhdCCwIz4tz6CH9UhyjFv+Dpp6m05lJ9DnPfzwqaheLnvZMOH7B9jkZQdXR
QrATLy7RkHGHfYRepb+ReTiyU4jHVN9WPiieS3rv8RIj39639IeWh9erqAMBNG+z
Co/TzRRC7Nm5GonlzWozBV9QqrR2SjcLLmfmBcYlGOG24b9xJjactOIKbwIDAQAB
oEgwRgYJKoZIhvcNAQkOMTkwNzA1BgNVHREELjAsgRBhZG1pbkB1cy5pYm0uY29t
hwTAqAHdghJ3d3cuZm9vYmFyLmlibS5jb20wDQYJKoZIhvcNAQEFBQADggEBAFGi
I7umaDAWHzu7VTRbdjdmEbHiGHaojfTOSFUyP4NV8YvcgszVNVE8cEGzTcXUmcdV
/RZJv0GvPx5VGdAfgB/aQBP3Z9JekJS1VEJN9T7E5nyDqJDkobGUVUJVKjWT9lt0
YfrF6g5AQtV1uT3yvx5EkyWCG7jGOBlJOb550wGAVgMnNV32GtzP6v0z2sWUDVHR
ypuu/TaWD9iG0+M5EMVIABuUslnc2LjtTM8sr26UR2UcQJYxkcTXXHVwmaNdjlm1
AkYJfYGgMm6G4smZWfUjC43QkLhsnNkgLSiAYuzVlrn6xJZ98BzfyYgvX40RwAdN
UPKFJdZz3etLIH9+IRs=
-----END NEW CERTIFICATE REQUEST-----


which can then be sent off to the Certificate Authority (CA) for action.

Some required reading: -




WebSphere Application Server - Using WSAdmin to manage users and groups

print AdminTask.searchUsers(["-cn *"]) 

uid=wasadmin,o=defaultWIMFileBasedRealm
uid=wmbadmin,o=defaultWIMFileBasedRealm
uid=deAdmin,o=defaultWIMFileBasedRealm

 
print AdminTask.searchGroups(["-cn *"])

cn=developers,o=defaultWIMFileBasedRealm
cn=administrators,o=defaultWIMFileBasedRealm
cn=dashboard-editor,o=defaultWIMFileBasedRealm
cn=dashboard-viewer,o=defaultWIMFileBasedRealm


print AdminTask.help('-commands')

...
WASX8004I: Available admin commands: 

WIMCheckPassword - Validates the user/pasword in the Federated repositories user registry
addAdminIdToUserRegObj - Adds the adminId to the user registry object in the security.xml file
addCompUnit - Add a composition unit, based on an asset or another business-level application, to a business-level application.
addDisabledSessionCookie - Adds a cookie configuration that applications will not be able to programmatically modify
addExternalBundleRepository - Adds an external bundle repository to the configuration.  Requires a repository name and a URL.
addFeaturesToServer - Add feature pack or stack product features to existing server 
addFileRegistryAccount - Adds an account to the file registry.
addGroupToBusConnectorRole - Give a group permission to connect to the bus specified.
addGroupToDefaultRole - Grants a group default access to all local destinations on the bus for the specified role.
addGroupToDestinationRole - Grants a group access to a destination for the specified destination role.
addGroupToForeignBusRole - Grants a group access to a foreign bus from the local bus specified for the specified destination role.
addGroupToTopicRole - Gives a group permission to access the topic for the specified role.
addGroupToTopicSpaceRootRole - Gives a group permission to access the topic space for the specified role.
addIdMgrLDAPAttr - Adds an LDAP attribute configuration to the LDAP repository configuration.
addIdMgrLDAPAttrNotSupported - Adds a configuration for a virtual member manager property not supported by a specific LDAP repository.
addIdMgrLDAPBackupServer - Sets up a backup LDAP server.

...
 
print AdminTask.getMembersOfGroup(['-uniqueName','cn=dashboard-editor,o=defaultWIMFileBasedRealm'])

 uid=wasadmin,o=defaultWIMFileBasedRealm

print AdminTask.getMembershipOfUser(['-uniqueName',uid=wasadmin,o=defaultWIMFileBasedRealm'])

cn=developers,o=defaultWIMFileBasedRealm
cn=dashboard-editor,o=defaultWIMFileBasedRealm


which is nice.