Chapter 4. 安全

Security in JSR-160 remoting is an all-or-nothing option. Either all or none of your MBeans are accessible (except when your application server uses a SecurityManager, but that is not often the case). Jolokia, on the other hand, allows for fine grained security defined in an XML security policy file. It allows for access restrictions on MBean names (or patterns), attributes, operations, source IP address (or a subnet) and type of Jolokia operation.

Access to MBean and to the Jolokia agents in general can be restricted with an XML policy file. This policy can be configured for various parameters and is divided into several sections.

Overall access can be granted based on the IP address of an HTTP client. These restrictions are specified within a <remote> section, which contains one or more <host> elements. The source can be given either as an IP address, a host name, or a netmask given in CIDR format (e.g. "10.0.0.0/16" for all clients coming from the 10.0 network). The following allows access from localhost and all clients whose IP addresses start with "10.0". For all other IP addresses access is denied.

<remote>
  <host>localhost</host>
  <host>10.0.0.0/16</host>
</remote>

4.1.2. 命令

This section specifies the Jolokia commands for which access is generally granted. For each command in the list, access can be further restricted within the <deny> part and each command missing in the list, which is forbidden globally, can be selectively enabled for certain MBeans in the <allow> section. If the <commands> section is missing completely, access to all commands is allowed.

All Jolokia commands described in Chapter 6, Jolokia Protocol can be used in this section:

read
Reading of MBean attributes
write
Setting of MBean attributes
exec
Execution of JMX operations
list
List the available MBeans along with their supported attributes and operations.
search
Searching for MBeans
version
Getting version and server information

In the following example, access is granted to the read, list, search and version command, but not to write and exec operations.

<commands>
  <command>read</command>
  <command>list</command>
  <command>version</command>
  <command>search</command>
</commands>

Within an <allow> section, access to MBeans can be granted regardless of the operations specified in the <commands> section. The reverse is true for the <deny> section: It rejects access to the MBeans specified here. Both sections contain one or more <mbean> elements which have a format like:

<mbean>
  <name>java.lang:type=Memory</name>
  <attribute>*Memory*</attribute>
  <attribute mode="read">Verbose</attribute>
  <operation>gc</operation>
</mbean>        

Within the <name> section the name of the MBean is specified. This can bei either a complete ObjectName or a MBean pattern containing wildcards. The value given here must conform to the JMX specification for a valid ObjectName. On this MBean (or MBeans if name is a pattern), attributes are specified within one or more <attribute> elements and operations within one or more <operation> elements. The content can also be a pattern, which uses a wildcard *. e.g. <attribute>*</attribute> specifies all attributes on the given MBean. If for an <attribute> element the XML attribute mode="read" is given, then this attribute can be accessed only read-only.

Finally, access can be restricted based on the HTTP method with which an Jolokia request was received with the <http> element. Method allowed (post or get) are specified with an <method> inner element. The following example restricts the access to POST requests only:

<http>
  <method>post</method>
</http>        

It the <http> section is missing completely, any HTTP method can be used.

Jolokia (since version 1.0.3) supports the W3C specification for Cross-Origin Resource Sharing (also known as "CORS") which allows browser to access resources which are located on a different server than the calling script is loaded from. This specification provides a controlled way to come around the same origin policy. Most contemporary browsers support CORS.

By default Jolokia allows cross origin access from any host. This can be limited to certain hosts by using <allow-origin> sections within a <cors> sections. This tags can contain the origin URL provided by browsers with the Origin: header literally or a wildcard specification with *.

<cors>
   <!-- Allow cross origin access from www.jolokia.org ... -->
   <allow-origin>http://www.jolokia.org</allow-origin>

   <!-- ... and all servers from jmx4perl.org with any protocol ->
   <allow-origin>*://*.jmx4perl.org</allow-origin>
</cors>

The following complete example applies various access restrictions:

  • Access is only allowed for clients coming from localhost
  • Only HTTP Post requests are allowed
  • By default, only read and list requests are allowed.
  • A single exec request is allowed for triggering garbage collection.
  • Read access to the C3P0 connection pool is restricted to forbid fetching the pool's properties, which in fact contains the DB password as clear text.
<?xml version="1.0" encoding="utf-8"?>

<restrict>

  <remote>
    <host>127.0.0.1</host>
  </remote>

  <http>
    <method>post</method>
  </http>

  <commands>
    <command>read</command>
    <command>list</command>
  </commands>

  <allow>
    <mbean>
      <name>java.lang:type=Memory</name>
      <operation>gc</operation>
    </mbean>
  </allow>

  <deny>
    <mbean>
      <name>com.mchange.v2.c3p0:type=PooledDataSource,*</name>
      <attribute>properties</attribute>
    </mbean>
  </deny>

</restrict>

But how do the agents lookup the policy file ? By default, the agents will lookup for a policy file top-level in the classpath under the name jolokia-access.html. Hence for the war agent, the policy file must be packaged within the war at WEB-INF/classes/jolokia-access.xml, for all other agents at /jolokia-access.xml. The location can be overwritten with the configuration parameter policyLocation, which has to be set differently depending on the agent type. Please refer to Chapter 3, Agents for more details. The value of this init parameter can be any URL which can loaded by the JVM. A special case is an URL with the scheme classpath: which results in a lookup of the policy file within the classpath. As stated above, the default value of this parameter is classpath:/jolokia-access.xml. If a non-classpath URL is provided with this parameter, and the target policy file could not be found then access is completely denied. If a classpath lookup fails then access is globally granted and a warning is given on standard output.

4.2. Jolokia 限制

In order to provide fine grained security, Jolokia using the abstract concept of an Restrictor. It is represented by the Java interface org.jolokia.restrictor.Restrictor and comes with several implementations. The most prominent one is the PolicyRestrictor which is described in Section 4.1, “Policy based security”. This is also the restrictor which is active by default. For special needs, it is possible to provide a custom implementation of this interface for the WAR and OSGi agents. It is recommended to subclass either org.jolokia.restrictor.AllowAllRestrictor or org.jolokia.restrictor.DenyAllRestrictor.

For the WAR agent (Section 3.1, “JEE Agent (WAR)”), a subclass of org.jolokia.http.AgentServlet should be created which overrides the createRestrictor()

public class RestrictedAgentServlet extends AgentServlet {
    
    @Override
    protected Restrictor createRestrictor(String policyLocation) {
        return new MyOwnRestrictor();
    }
}

policyLocation is a URL pointing to the policy file, which is either the default value classpath:/jolokia-access.xml or the value specified with the init parameter policyLocation. This servlet can then be easily configured in a custom web.xml the same way as the Jolokia agent.

For programmatic usage there is an even simpler way: AgentServlet provides an constructor which takes an restrictor as argument, so no sublcassing is required in this case.

For an OSGi agent (Section 3.2, “OSGi Agents”), org.jolokia.osgi.servlet.JolokiaServlet is the proper extension point. It can be subclassed the same way as shown above and allows a restrictor implementation as constructor parameter, too. In contrast to AgentServlet this class is also OSGi exported and can be referenced from other bundles. Additionally, the OSGi agent can also pick up a restrictor as an OSGi service. See Section 3.2, “OSGi Agents” for details.