Using JMX Security





Using JMX Security

One of the interesting things about Java 2 Platform security is that using it has very little impact on your code. Application code that just wants to take advantage of the security features built into the classes it is using only needs to handle the additional failure cases—that is, instances of SecurityException—that may arise, and it is ready to run with Java security enabled. No messing about with permissions, security managers, and so on is required. The next time you bump into Li Gong, or one of the other Java 2 Platform security designers, shake their hand!

Of course there is no free lunch. Security is a complex business, and if the complexity doesn't show up in the application code, it must be dealt with elsewhere. Classes that provide security features manage some of that complexity by making calls to SecurityManager at the appropriate places. The remaining complexity is allocated to the Java 2 Platform security policy mechanism.

In this section we will demonstrate how to configure MX4J security policy. Starting with a simple application, we'll turn on security and then experiment with different security policies.

1 A Simple Process Management Application (SPMA)

Suppose that our operating system vendor of choice shipped a ProcessManager MBean with its operating systems. Here's a very minimal version of such an MBean:

public interface ProcessManagerMBean { 
  int[] getPids();
  void kill(int pid);
}

Let's further suppose that this interface, the MBean class that implements it, and some other OS-specific MBeans are packaged in osmbeans.jar.

Here is the main() method of a simple process management application that uses the ProcessManager MBean:

public class spma { 
  public static void main(String[] args) throws Exception {
      ObjectName pmname = new ObjectName("ch8:id=ProcessManager");
      MBeanServer mbs = setupProcessManager(pmname);
      char cmd;
      System.out.print("% ");
      while ((cmd = readcmd()) != 'q') {
          switch (cmd) {
              case 'l' :
                  doListCmd(mbs, pmname);
                  break;
              case 'k' :
                  doKillCmd(mbs, pmname);
                  break;
              default :
                  usage(cmd);
          }
          System.out.print("% ");
      }
  }

  …
}

The setupProcessManager() method uses MBeanServerFactory to create an MBeanServer and then uses that server to create a ProcessManager MBean. The doListCmd() and doKillCmd() methods invoke the ProcessManager MBean's getPids() and kill() operations via the MBeanServer.

A user runs spma from the command line by typing

$ java net.jnjmx.ch8.spma 

Here's a snapshot of an spma session that gets a list of pids, kills 8502, then gets a new list of pids to verify that 8502 is gone:

% l 
pids: [9064, 8502, 2025, 2446, 4629, 1396, 4147, 7231, 6878, 922,
       9324, 7610]
% k 8502
% l
pids: [9064, 2025, 2446, 4629, 1396, 4147, 7231, 6878, 922, 9324,
       7610]
% q

Obviously this is not something we want an arbitrary user to be able to do. So let's look at how we can make it more secure.

2 Running with Security Enabled

By default the java command does not instantiate SecurityManager in the JVM that it creates to execute Java programs. Because SecurityManager is responsible for enforcing Java security, the first thing to do is to run spma with SecurityManager. To do that, we specify the java.security.manager and java.security.policy system properties on the command line:

$ java –Djava.security.manager –Djava.security.policy=/home/wkh/spma.policy net.jnjmx.ch8.
graphics/ccc.gifspma 

If we absolutely, positively never want spma to run without SecurityManager, we can also modify its main() method as follows:

public class spma { 
    public static void main(String[] args) throws Exception {
        SecurityManager sm = System.getSecurityManager();
        if (sm == null) {
            System.err.println(
                "spma must be run with a SecurityManager");
            System.exit(-1);
        }
        …
    }
}

Note that rather than specify the java.security.policy system property on the command line, we could add an additional policy.url entry to the ${JRE_HOME}/lib/security/java.security file. That is, if we add the entry

policy.url.3=/home/wkh/spma.policy 

then the command line above can be shortened to

$ java –Djava.security.manager net.jnjmx.ch8.spma 

3 Policy Configuration

When spma is run with security enabled on a standard J2SE installation with no spma-specific policy, it fails with an AccessControlException. That's actually a good thing; it indicates that SecurityManager is on the job, and because none of the code we're running has any JMX-specific permissions, it doesn't get to run. Of course, it would be even better to be able to use spma with security enabled. How do we do that?

First we have to grant the necessary permissions to MX4J itself. To do that, we add the following grant block to spma.policy:

grant codeBase "file:/opt/mx4j/*" { 
  permission javax.management.MBeanServerPermission 
    "createMBeanServer";
  permission mx4j.server.MBeanPermission "*", 
    "getAttribute,setAttribute,invokeOperation";
};

The first line says that we're granting permissions to code that is loaded from file:/opt/mx4j/, which is where all the MX4J .jar files live. The permissions we're granting are indicated by the two permission statements. The first one grants MX4J access to all the MBeanServerFactory methods. The second line grants MX4J access to all MBean attributes and operations.

Next we have to give spma the access it needs to the MBeanServer and MBean resources. So we add another grant block to spma.policy:

grant codeBase "file:/opt/admin/spma/" { 
  permission javax.management.MBeanServerPermission 
    "createMBeanServer";

  permission mx4j.server.MBeanPermission 
    "net.jnjmx.ch8.ProcessManager#*[ch8:*]",
    "newMBean,registerMBean,getAttribute,invokeOperation, 
unregisterMBean";
}

This block grants code loaded from file:/opt/admin/spma/ permission to create an MBeanServer. Then it grants permission to invoke operations on and get attributes of any MBeans in packages rooted at net.jnjmx.ch8.

Finally, because we want to make sure that spma uses only legitimate MBeans, we express "trust" in MBeans loaded from file:/usr/lib/osmbeans.jar by adding this grant block:

grant codeBase "file/usr/lib/osmbeans.jar" { 
  permission mx4j.server.MBeanTrustPermission "register";
};

     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows