23 詳細なセキュリティ

JMX APIは、接続を保護するために既存のセキュリティ・プロトコルを使用します。この例では、詳細なセキュリティの実装を提供します。この項に含まれるソース・コードを使用して、適切な設定手順で指定したexamples/ディレクトリに対応するファイルが作成され、次の内容が含まれます。

警告:

セキュリティ・マネージャおよびそれに関連するAPIは非推奨であり、今後のリリースでは削除されます。セキュリティ・マネージャの代わりとなるものはありません。詳細および代替手段については、JEP 411を参照してください。
  • README file

  • Server

  • Client

  • ClientListener

  • keystore

  • password.properties

  • truststore

  • java.policy

  • SimpleStandard

  • SimpleStandardMBean

examples/Security/fine_grained/README


# ==============================================================================
#
#  Example of a secure RMI connector (using Security Manager and Policy File).
#
#  This example uses:
#
#  - the RMI SSL socket factories for encryption,
#  - the password authenticator based on the JMXAuthenticator interface for
#    user authentication,
#  - the JAAS and the J2SE Security Architecture based on the use of security
#    managers and policy files for user access level authorization.
#
# ==============================================================================
#
# In order to compile and run the example, make a copy of this README file, and
# then simply cut and paste all the commands as needed into a terminal window.
#
# This README makes the assumption that you are running under Java SE 6 on Unix,
# you are familiar with the JMX technology, and with the bourne shell or korn
# shell syntax.
#
# All the commands below are defined using Unix korn shell syntax.
#
# If you are not running Unix and korn shell you are expected to be able to
# adapt these commands to your favorite OS and shell environment.
#

# Compile Java classes
#
# * Server.java: creates an MBeanServer and creates and starts a secure RMI
#                connector server (JRMP).
#
# * Client.java: creates a secure RMI connector (JRMP), creates and registers
#                a Simple standard MBean and performs operations on it.
#
# * ClientListener.java: implements a generic notification listener.
#
# * SimpleStandard.java: implements the Simple standard MBean.
#
# * SimpleStandardMBean.java: the management interface exposed by the Simple
#                             standard MBean.
#

javac mbeans/SimpleStandard.java \
      mbeans/SimpleStandardMBean.java \
      server/Server.java \
      client/Client.java \
      client/ClientListener.java

# Start the RMI registry:
#

export CLASSPATH=server ; rmiregistry 9999 &

# Start the Server:
#

java -classpath server:mbeans \
     -Djavax.net.ssl.keyStore=config/keystore \
     -Djavax.net.ssl.keyStorePassword=password \
     -Djava.security.manager \
     -Djava.security.policy=config/java.policy \
     Server &

# Start the Client:
#

java -classpath client:server:mbeans \
     -Djavax.net.ssl.trustStore=config/truststore \
     -Djavax.net.ssl.trustStorePassword=trustword \
     Client

# ==============================================================================

examples/Security/fine_grained/server/Server.java



import java.io.File;
import java.util.HashMap;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnectorServer;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;

public class Server {

    public static void main(String[] args) {
        try {
            // Instantiate the MBean server
            //
            System.out.println("\nCreate the MBean server");
            MBeanServer mbs = MBeanServerFactory.createMBeanServer();

            // Environment map
            //
            System.out.println("\nInitialize the environment map");
            HashMap env = new HashMap();

            // Provide SSL-based RMI socket factories.
            //
            SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();
            SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory();
            env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,csf);
            env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,ssf);

            // Provide the password file used by the connector server to
            // perform user authentication. The password file is a properties
            // based text file specifying username/password pairs. This
            // properties based password authenticator has been implemented
            // using the JMXAuthenticator interface and is passed to the
            // connector through the "jmx.remote.authenticator" property
            // in the map.
            //
            // This property is implementation-dependent and might not be
            // supported by all implementations of the JMX Remote API.
            //
            env.put("jmx.remote.x.password.file",
                    "config" + File.separator + "password.properties");

            // Create an RMI connector server
            //
            System.out.println("\nCreate an RMI connector server");
            JMXServiceURL url = new JMXServiceURL(
              "service:jmx:rmi:///jndi/rmi://localhost:9999/server");
            JMXConnectorServer cs =
                JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);

            // Start the RMI connector server
            //
            System.out.println("\nStart the RMI connector server");
            cs.start();
            System.out.println("\nRMI connector server successfully started");
            System.out.println("\nWaiting for incoming connections...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

examples/Security/fine_grained/client/Client.java



import java.util.HashMap;
import javax.management.Attribute;
import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class Client {

    public static void main(String[] args) {
        try {
            // Environment map
            //
            System.out.println("\nInitialize the environment map");
            HashMap env = new HashMap();

            // Provide the credentials required by the server to successfully
            // perform user authentication
            //
            String[] credentials = new String[] { "username" , "password" };
            env.put("jmx.remote.credentials", credentials);

            // Create an RMI connector client and
            // connect it to the RMI connector server
            //
            System.out.println("\nCreate an RMI connector client and " +
                               "connect it to the RMI connector server");
            JMXServiceURL url = new JMXServiceURL(
              "service:jmx:rmi:///jndi/rmi://localhost:9999/server");
            JMXConnector jmxc = JMXConnectorFactory.connect(url, env);

            // Get an MBeanServerConnection
            //
            System.out.println("\nGet an MBeanServerConnection");
            MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

            // Get domains from MBeanServer
            //
            System.out.println("\nDomains:");
            String domains[] = mbsc.getDomains();
            for (int i = 0; i < domains.length; i++) {
                System.out.println("\tDomain[" + i + "] = " + domains[i]);
            }

            // Create SimpleStandard MBean
            //
            ObjectName mbeanName = new ObjectName("MBeans:type=SimpleStandard");
            System.out.println("\nCreate SimpleStandard MBean...");
            mbsc.createMBean("SimpleStandard", mbeanName, null, null);

            // Get MBean count
            //
            System.out.println("\nMBean count = " + mbsc.getMBeanCount());

            // Get State attribute
            //
            System.out.println("\nState = " +
                               mbsc.getAttribute(mbeanName, "State"));

            // Set State attribute
            //
            mbsc.setAttribute(mbeanName,
                              new Attribute("State", "changed state"));

            // Get State attribute
            //
            // Another way of interacting with a given MBean is through a
            // dedicated proxy instead of going directly through the MBean
            // server connection
            //
            SimpleStandardMBean proxy = JMX.newMBeanProxy(
                    mbsc, mbeanName, SimpleStandardMBean.class);
            System.out.println("\nState = " + proxy.getState());

            // Add notification listener on SimpleStandard MBean
            //
            ClientListener listener = new ClientListener();
            System.out.println("\nAdd notification listener...");
            mbsc.addNotificationListener(mbeanName, listener, null, null);

            // Invoke "reset" in SimpleStandard MBean
            //
            // Calling "reset" makes the SimpleStandard MBean emit a
            // notification that will be received by the registered
            // ClientListener.
            //
            System.out.println("\nInvoke reset() in SimpleStandard MBean...");
            mbsc.invoke(mbeanName, "reset", null, null);

            // Sleep for 2 seconds in order to have time to receive the
            // notification before removing the notification listener.
            //
            System.out.println("\nWaiting for notification...");
            Thread.sleep(2000);

            // Remove notification listener on SimpleStandard MBean
            //
            System.out.println("\nRemove notification listener...");
            mbsc.removeNotificationListener(mbeanName, listener);

            // Unregister SimpleStandard MBean
            //
            System.out.println("\nUnregister SimpleStandard MBean...");
            mbsc.unregisterMBean(mbeanName);

            // Close MBeanServer connection
            //
            System.out.println("\nClose the connection to the server");
            jmxc.close();
            System.out.println("\nBye! Bye!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

examples/Security/fine_grained/client/ClientListener.java


import javax.management.Notification;
import javax.management.NotificationListener;

public class ClientListener implements NotificationListener {
    public void handleNotification(Notification notification, Object handback) {
        System.out.println("\nReceived notification: " + notification);
    }
}

examples/Security/fine_grained/config/password.properties



# password.properties

# Password file for Remote JMX API authentication. This file defines
# the different roles and their passwords.

# The file format for the password file is syntactically the same as
# the Properties file format. The syntax is described in the JavaDoc page
# for java.util.Properties.load.

# A typical password file has multiple lines, where each line is blank,
# a comment (like this one), or a password entry.

# A password entry consists of a role name and an associated password.
# The role name is any string that does not itself contain spaces or
# tabs. The password is again any string that does not contain spaces
# or tabs. Note that passwords appear in the clear in this file, so it
# is a good idea not to use valuable passwords.

# A given role should have at most one entry in this file. If a role
# has no entry, it has no access.
# If multiple entries are found for the same role name, then the last
# one is used.

# In a typical installation, this file can be read by anybody on the
# local machine, and possibly by people on other machines.
# For security, you should either restrict the access to this file,
# or specify another, less accessible file in the management config
# file as described above.

# Role and password used for authentication by the RMI connector in
# this example.
#
username password

examples/Security/fine_grained/config/java.policy

grant codeBase "file:server" {
    //
    // The server requires the permissions to create and register the connector
    // and all the permissions required by the operations performed by remote
    // user calls. Here AllPermission is granted for simplicity.
    //
    permission java.security.AllPermission;
};

grant codeBase "file:mbeans" {
    permission javax.management.MBeanTrustPermission "register";
};

grant principal javax.management.remote.JMXPrincipal "username" {
    permission javax.management.MBeanPermission "*", "getDomains";
    permission javax.management.MBeanPermission "SimpleStandard#-[-]", "instantiate";
    permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "registerMBean";
    permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
    permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
    permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
    permission javax.management.MBeanPermission "SimpleStandard#reset[MBeans:type=SimpleStandard]", "invoke";
    permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "removeNotificationListener";
    permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
    //
    // This permission is only required for the authenticated user and not for the delegated users.
    //
    // The RMI connector client registers a listener on the MBeanServerDelegate to control the MBean
    // creation/deletion. The listener is removed when the connection to the server is closed.
    //
    permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
    permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
};

examples/Security/fine_grained/mbeans/SimpleStandard.java


/**
 * Simple definition of a standard MBean, named "SimpleStandard".
 *
 * The "SimpleStandard" standard MBean shows how to expose attributes
 * and operations for management by implementing its corresponding
 * "SimpleStandardMBean" management interface.
 *
 * This MBean has two attributes and one operation exposed
 * for management by a JMX agent:
 *      - the read/write "State" attribute,
 *      - the read only "NbChanges" attribute,
 *      - the "reset()" operation.
 *
 * This object also has one property and one method not exposed
 * for management by a JMX agent:
 *      - the "NbResets" property,
 *      - the "getNbResets()" method.
 */

import javax.management.AttributeChangeNotification;
import javax.management.MBeanNotificationInfo;
import javax.management.NotificationBroadcasterSupport;

public class SimpleStandard
    extends NotificationBroadcasterSupport
    implements SimpleStandardMBean {

    /*
     * -----------------------------------------------------
     * CONSTRUCTORS
     * -----------------------------------------------------
     */

    /* "SimpleStandard" does not provide any specific constructors.
     * However, "SimpleStandard" is JMX compliant with regards to
     * contructors because the default contructor SimpleStandard()
     * provided by the Java compiler is public.
     */

    /*
     * -----------------------------------------------------
     * IMPLEMENTATION OF THE SimpleStandardMBean INTERFACE
     * -----------------------------------------------------
     */

    /**
     * Getter: get the "State" attribute of the "SimpleStandard" standard MBean.
     *
     * @return the current value of the "State" attribute.
     */
    public String getState() {
        return state;
    }

    /**
     * Setter: set the "State" attribute of the "SimpleStandard" standard MBean.
     *
     * @param <VAR>s</VAR> the new value of the "State" attribute.
     */
    public void setState(String s) {
        state = s;
        nbChanges++;
    }

    /**
     * Getter: get the "NbChanges" attribute of the "SimpleStandard" standard
     * MBean.
     *
     * @return the current value of the "NbChanges" attribute.
     */
    public int getNbChanges() {
        return nbChanges;
    }

    /**
     * Operation: reset to their initial values the "State" and "NbChanges"
     * attributes of the "SimpleStandard" standard MBean.
     */
    public void reset() {
        AttributeChangeNotification acn =
            new AttributeChangeNotification(this,
                                            0,
                                            0,
                                            "NbChanges reset",
                                            "NbChanges",
                                            "Integer",
                                            new Integer(nbChanges),
                                            new Integer(0));
        state = "initial state";
        nbChanges = 0;
        nbResets++;
        sendNotification(acn);
    }

    /*
     * -----------------------------------------------------
     * METHOD NOT EXPOSED FOR MANAGEMENT BY A JMX AGENT
     * -----------------------------------------------------
     */

    /**
     * Return the "NbResets" property.
     * This method is not a Getter in the JMX sense because it
     * is not exposed in the "SimpleStandardMBean" interface.
     *
     * @return the current value of the "NbResets" property.
     */
    public int getNbResets() {
        return nbResets;
    }

    /**
     * Returns an array indicating, for each notification this MBean
     * may send, the name of the Java class of the notification and
     * the notification type.</p>
     *
     * @return the array of possible notifications.
     */
    public MBeanNotificationInfo[] getNotificationInfo() {
        return new MBeanNotificationInfo[] {
            new MBeanNotificationInfo(
            new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE },
            AttributeChangeNotification.class.getName(),
            "This notification is emitted when the reset() method is called.")
        };
    }

    /*
     * -----------------------------------------------------
     * ATTRIBUTES ACCESSIBLE FOR MANAGEMENT BY A JMX AGENT
     * -----------------------------------------------------
     */

    private String state = "initial state";
    private int nbChanges = 0;

    /*
     * -----------------------------------------------------
     * PROPERTY NOT ACCESSIBLE FOR MANAGEMENT BY A JMX AGENT
     * -----------------------------------------------------
     */

    private int nbResets = 0;
}

examples/Security/fine_grained/mbeans/SimpleStandardMBean.java


/**
 * This is the management interface explicitly defined for the
 * "SimpleStandard" standard MBean.
 *
 * The "SimpleStandard" standard MBean implements this interface
 * in order to be manageable through a JMX agent.
 *
 * The "SimpleStandardMBean" interface shows how to expose for management:
 * - a read/write attribute (named "State") through its getter and setter
 *   methods,
 * - a read-only attribute (named "NbChanges") through its getter method,
 * - an operation (named "reset").
 */
public interface SimpleStandardMBean {

    /**
     * Getter: set the "State" attribute of the "SimpleStandard" standard
     * MBean.
     *
     * @return the current value of the "State" attribute.
     */
    public String getState();

    /**
     * Setter: set the "State" attribute of the "SimpleStandard" standard
     * MBean.
     *
     * @param <VAR>s</VAR> the new value of the "State" attribute.
     */
    public void setState(String s);

    /**
     * Getter: get the "NbChanges" attribute of the "SimpleStandard" standard
     * MBean.
     *
     * @return the current value of the "NbChanges" attribute.
     */
    public int getNbChanges();

    /**
     * Operation: reset to their initial values the "State" and "NbChanges"
     * attributes of the "SimpleStandard" standard MBean.
     */
    public void reset();
}