<< May 2013 | Home | July 2013 >>

New cool reference story about IBM Connections and OnTime Group Calendar

Good news - yesterday night a new IBM reference story for one of our Danish customers went online. The reference is for Semler Group and talks about their adoption of Social Business using IBM Connections as a platform and how the social components from OnTime Group Calendar are central pieces in this strategy. The reference story is also available as a PDF.

Java in Notes/Domino Explained: On Java Security and how it relates to Notes/Domino

I get so many questions on Java security and how it all fits together that I finally decided to blog it instead of simply answering over and over again. So here goes...

Security was built into Java from its inception and everything in a Java Virtual Machine (JVM) runs under the control of a security manager. Now the security manager may be very lax or it may be very restrictive as the one for Java applets or Notes/Domino agents is. A security manager is installed into the JVM when it's constructed meaning either from the command line or, in the case of Notes/Domino, when a JVM is created to run agents, XPages or the like. A security manager may decide that a certain operation (method call) is "powerful" and hence will require the code executing the operation to be allowed to do so.

The way this is done in Java is by the operation itself (the method you are calling e.g. "write file" or "do stuff with reflection") asking the security manager whether the code calling it has a given permission that it supplies to the security manager. The security manager may either decide that it does and hence return quietly or it may decide that the calling code does not have the required permission. To signal the latter it will throw a java.security.AccessControlException which you've seen if you're reading this.

So how do we grant these permissions?

In Java permissions are controlled in the java.policy file located in the file system under <notes>/jvm/lib/security or <domino>/jvm/lib/security. I will not go into detail on the syntax of this file as resources are readily available on the web but suffice to say that different locations (be those file based or network based) are granted different sets of permissions (for more info see http://docs.oracle.com/javase/6/docs/technotes/guides/security/PolicyFiles.html). By default jar-files in jvm/lib/ext, the XPages runtime, OSGi bundles etc. are granted all permissions possible (java.security.AllPermission) whereas other code is granted a limited set of permissions. So if you need to run code that requires a different set of permissions you edit this file and restart the server/client. Now often times simply editing this file is not an option. Either you do not control the server, you cannot edit it for all clients or your security guidelines tell you just can't do it. In either case editing the file is seldom the entire solution. And you need to understand why. Before showing you some code let me explain the scenario I'm going to use below first.

The scenario is that Joe Notes Developer needs to use reflection (wikipedia) to change the accessibility of a method from private to public (yes it's possible) to override the private restriction set on the generate() method of the Test class (see below). To do this he uses a method like the one below:

public void doAccessible(Object obj) throws Exception {
   Method[] methods = obj.getClass().getMethods();
   for (int i=0; i<methods.length; i++) {
      Method m = methods[i];
      m.setAccessible(true);
   }
}
The class he needs to affect is likewise simple (he needs to make the generate() method public):
private class Test {
   private String uuid = null;
   
   public Test() {
      this.generate();
   }
   
   public String getUUID() {
      return this.uuid;
   }
   
   private void generate() {
      this.uuid = UUID.randomUUID().toString();
   }
}
To start of Joe Notes Developer creates a Java agent in Domino Designer and sticks the below code in NotesMain of the agent:
Test t = new Test();
System.out.println(t.getUUID());
doAccessible (t);
t.generate();
System.out.println(t.getUUID());
System.out.println("Completed...");
But oh no!! Joe gets the dreaded AccessControlExeption as the code in the Java agent may not use reflection this way.
java.security.AccessControlException: Access denied (java.lang.reflect.ReflectPermission suppressAccessChecks)
   at java.security.AccessController.checkPermission(AccessController.java:132)
   at java.lang.SecurityManager.checkPermission(SecurityManager.java:544)
   at COM.ibm.JEmpower.applet.AppletSecurity.superDotCheckPermission(AppletSecurity.java:1449)
   at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1617)
   at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1464)
   at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:118)
   at ReflectionUtil.doAccessible(Unknown Source)
   at JavaAgent.NotesMain(Unknown Source)
   at lotus.domino.AgentBase.runNotes(Unknown Source)
   at lotus.domino.NotesThread.run(Unknown Source)
Nothing is holding Joe back though so he puts the reflection code into a ReflectionUtil class which he puts in a jar-file in jvm/lib/ext as he has heard that this location allows for this kind of funky stuff. Using the ReflectionUtil instead of a class method from his agent is like this:
ReflectionUtil l = new ReflectionUtil();
Test t = new Test();
System.out.println(t.getUUID());
l.doAccessible(t);
t.generate();
System.out.println(t.getUUID());
System.out.println("Completed...");
Arrrghhhh no!! He still gets an AccessControlException. But how can this be?? He did put the code in the special jvm/lib/ext folder which is granted AllPermissions. Hmmm...

The reason is that security in Java is layered and it's the layer or "context" in Java parlance initiating the call that decides which permissions are assigned. This is why simply making a call from a Java agent in Notes/Domino to a Java library in jvm/lib/ext that need permissions other than the default set doesn't just work. It doesn't work because it's the context of the Java agent which is in effect. So wouldn't it be great if you could change the context? Well you can... :) This is done using the java.security.AccessController class (docs). The AccessController class is a nifty little thing. It works by you supplying an instance of the java.security.PrivilegedAction interface which is an interface with a single method called run. Inside the run-method you put the code requiring special permissions. Below is an example of using the AccessController class:

AccessController.doPrivileged(new PrivilegedExceptionAction() {
   public Object run() throws Exception {
      ReflectionUtil l = new ReflectionUtil();
      Test t = new Test();
      l.doAccessible(t);
      System.out.println("Completed...");
      return null;
   }
});
But wouldn't you know it - this also fails! Of course the reason is quite obvious - I think - we cnanot just have developers go ahead elevating their persmissions themselves. As Paul Mooney would say - developers mus be controlled and kept down. It needs to be the privileged code meaning the code in jvm/lib/etc that needs to elevate the permissions. To do this we move the AccessController call info the ReflectionUtil in a special "doAccessiblePrivileged" method as this code can then decide to elevate permissions as it runs from a location with a higher security context. The code in the agent is therefor now like this (change in bold):
ReflectionUtil l = new ReflectionUtil();
Test t = new Test();
System.out.println(t.getUUID());
l.doAccessiblePrivileged(t);
t.generate();
System.out.println(t.getUUID());
System.out.println("Completed...");
And the code in ReflectionUtil looks like this:
public void doAccessiblePrivileged(final Object obj) throws Exception {
   AccessController.doPrivileged(new PrivilegedExceptionAction() {
      @Override
      public Object run() throws Exception {
         ReflectionUtil.this.doAccessible(obj);
         return null;
      }
   });
}
Now the code runs just fine as Joe is using code that knows that it might need to elevate the permissions so it provides a call doing just that (doAccessiblePrivileged).

Of course this can make it very difficult to just use a standard library from the web in Notes as it may not provide a way to elevate the permissions as no one ever saw that as a use case. In this case a wrapper API that elevates the permissions in jvm/lib/ext may be necessary to make it work.

Hope this explains it... :)

The example code is available for download including the required jar-file to put in jvm/lib/ext.

Social Connections V in Zurich - I'm speaking

I will be giving a condensed version of my An Introduction To Working With the Activity Stream presentation at the upcoiming Social Connections V event in Zurich on 28 June. I'll be in the development track (surprise, surprise) at 11:20. As I only have 30 minutes the session will be highly condensed but the full presentation with all the examples will still be available to get you up to speed.

Hope to see you there.

Blog interview on IBMSocialSoftware.com

Last week I was interviewed for the IBM Social Software Blog and the interview is now live here. The interview is on my work with the activity stream and how to get started working with the activity stream.

IBM SmartCloud - credit where credit is due

On Friday I blogged about the changes that occured on IBM SmartCloud over the weekend (SmartCloud getting an overhaul this weekend with changes that is looooong overdue) and how I was waiting for IBM to add proper Sametime support in SmartCloud meaning Sametime Proxy, Sametime webchat and Sametime app support. As it turns out these capabilities are available just not visible in the dashboard or otherwise readily obvious. So I will give IBM credit for adding it but why didn't I know?! Anyways - props to IBM.

So the Sametime webchat is available at webchat.na.collabserv.com/stwebclient/iphone_index.jsp and of course it also means that the Sametime Proxy is available. Whether we may use it for actual, 3rd party applications, I will need to find out. There are *still* some really annoying restrictions when it comes to the Sametime entitlement for Notes users (see this tweet). Still waiting for Scott Souder to come back on that one.

Another cool thing (which is an off-spring of the Sametime Proxy support) is that the iOS app works and Sametime availability works on my iPhone and iPad. And even better is that there is a pre-set community configuration for IBM SmartCloud so it's real easy to configure. Pretty sweet.

SmartCloud getting an overhaul this weekend with changes that is looooong overdue

This weekend (8-9 June 2013) IBM is releasing their June 2013 Update to the SmartCloud for Social Business. Besides layout changes and notes about the URL used to access the service IBM is finally adding support for the Microsoft Office connectors and the Windows Explorer connector so that, using "click to cloud", users may save, open and edit Office documents and other files directory from SmartCloud. This is of course a big win for users and a byproduct of IBM transitioning the SmartCloud offering to use more and more of the stock, on-premises, IBM Connections product. But this should still have been delivered before. Another byproduct is that of supporting the media gallery and mobile using the IBM Connections app from the Appstore.

For me as a SmartCloud Sametime user the most important thing is IBM allowing the use of the screen capture tool and file transfer in chat. FINALLY!!!!! These "advanced" capabilities are *long* overdue and will be a welcome addition to the service. Why this has taken so long is beyond me but great to finally see it added. Now we *just* IBM to also add IBM Sametime Proxy support so webchat and chat from the iOS app will be supported. Hoping this wont take as long as adding something simple as file transfer and screen capture has.

Oh and IBM is janking support for Microsoft IE 7.

For the full list of changes see the release notes (requires a SmartCloud for Social Business login). There are restrictions to the availability of these additions which are outlined in the release notes.

System user in IBM Connections activity stream needs to change

The other day I noticed an event in my activity stream for an activity that is about to be auto completed due to inactivity as shown in the screenshot below. There was no profile picture for this user so my first comment as "Hmmmmmm...." as all users posting to the activity stream in Connections must be in Profiles and hence would have a profile picture (in our environment).

actor: {
   objectType: "person",
   id: "urn:lsid:lconn.ibm.com:profiles.person:SYSTEM",
   displayName: "SYSTEM"
}

Looking futher into the matter by looking at the stream feed revealed that the actor ID was set to urn:lsid:lconn.ibm.com:profiles.person:SYSTEM. Even more hmmmmm..... This user was definitely not in Profiles so I sent my "Crazy activity stream question of the day™" to a contact at IBM and all was revealed. I turns out that this is a shortcut / workaround that was implemented for this particular purpose which they know is a hack. Unfortunately there is no way to change the user posting these events or set the profile picture of the user. This is really too bad and something that I hope is rectified in a future version.

To learn more about the activity stream and how to work with it I humbly recommend my An Introduction to Working With the Activity Stream" presentation on Slidehare.