Security

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.

Policy based security

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.

IP based restrictions

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>

Commands

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 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

search

Searching for MBeans

notification

New in Jolokia 2 Subscribing to and receiving notifications

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, notification and exec operations.

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

Allow and deny access to certain MBeans

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 be 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.

HTTP method restrictions

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.

Cross-Origin Resource Sharing (CORS) restrictions

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>https://www.jolokia.org</allow-origin>

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

  <!-- Check for the proper origin on the server side, too -->
  <strict-checking/>

  <!-- Use if Origin header can use https while the protocol is http (e.g., with TLS proxy) -->
  <ignore-scheme/>
</cors>

If the option <strict-checking/> is given in this section, too, then the given patterns are not only used for CORS checking but also every request is checked on the server side whether the Origin: or Referer: header matches one of the given patterns. If neither Origin: nor Referer: is given and strict checking is enabled, then the access is denied. This useful for protecting against Cross-Site Request Forgery.

Please note that <strict-checking/> might not be good enough because of potential browser bugs which could allow to forge the origin header. Examples of these issues are arbitrary header injection or referer and origin spoofing. User facing application which uses Jolokia has backend should consider to implement additional measures like using the same-site flag on the session cookie.

If the option <ignore-scheme/> is specified (it defaults to false when not used), Origin header using https scheme is not restricted to be used with https protocol only. This option may be required when Jolokia resides behind TLS proxy.

Disable listing/searching of selected MBeans

Using <filter> element we can filter out results of list and search operations (even if search parameters include such MBean names). It’s not preventing users to access given MBeans unless specific <deny> element is present, but it may be used to make list/search results shorter.

NOTE

This configuration option is available since Jolokia 2.1.0

Here’s the example:

<filter>
  <mbean>java.lang:type=MemoryPool</mbean>
  <mbean>org.apache.logging.log4j2:*</mbean>
</filter>

The pattern format is not exactly the same as the patter used for javax.management.MBeanServerConnection.queryNames(). Here’s a summary of rules:

  • * is a glob matching any number of characters except :, = or , (that’s specific to the format of ObjectName)

  • when there’s no : in MBean pattern, entire pattern is treated as domain and all MBeans within matching domain are filtered out

  • domain:* is the same as domain pattern and simply means all MBeans within a domain

  • domain:type=SomeType filters out MBeans within domain with type attribute equal to SomeType. For the purpose of MBeanServer.queryNames() the pattern would be domain:type=SomeType,*

  • domain:address=* filters out MBeans within domain with any value of address attribute

  • domain:address=Admin* filters out MBeans within domain with value of address attribute starting with Admin

Jolokia uses the above patterns individually for each ObjectName and uses these methods:

  • javax.management.ObjectName.getDomain() to access the domain

  • javax.management.ObjectName.getKeyPropertyList() and javax.management.ObjectName.getKeyProperty() to filter by attributes

For performance purposes there are some restrictions for using * within a pattern:

  • attribute keys can’t use *

  • there can be only one * within attribute value or domain name (Admin*, *Admin, Adm*in are correct, but *Admi*n* is not)

  • domain:* is simply treated as domain and matches (filters out) all MBeans within a domain

Example for a security policy

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.

  • Access to jdk.management.jfr:type=FlightRecorder MBean is denied (see CVE-2022-41678)

<?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>
    <mbean>
      <name>jdk.management.jfr:type=FlightRecorder</name>
      <attribute>*</attribute>
      <operation>*</operation>
    </mbean>
  </deny>

  <filter>
    <mbean>java.lang:type=MemoryPool</mbean>
    <mbean>org.apache.logging.log4j2:*</mbean>
  </filter>

</restrict>

Policy Location

A great tool which helps in repackaging an agent for inclusion of a jolokia-access.xml policy file is the command line tool jolokia, which comes with the jmx4perl distribution.

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.xml. 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 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.

The parameter specified with policyLocation can contain placeholders:

  • $ip: IP - Address

  • $host: Host - Address

  • ${prop:foo}: System property foo

  • ${env:FOO}: Environment variable FOO

Jolokia Restrictors

In order to provide fine grained security, Jolokia is using the abstract concept of an Restrictor. It is represented by the Java interface org.jolokia.server.core.service.api.Restrictor and comes with several implementations. The most prominent one is the PolicyRestrictor which is described in 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.server.core.restrictor.AllowAllRestrictor or org.jolokia.server.core.restrictor.DenyAllRestrictor.

For the WAR agent (Jakarta EE Agent (WAR)), a subclass of org.jolokia.server.core.http.AgentServlet should be created which overrides the createRestrictor()

public class RestrictedAgentServlet extends AgentServlet {

  @Override
  protected Restrictor createRestrictor(Configuration pConfig, LogHandler pLogHandler) {
    String policyLocation = pConfig.getConfig(ConfigKey.POLICY_LOCATION);
    return new MyOwnRestrictor(policyLocation, ...);
  }

}

pConfig is a configuration object from which we can get 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 WAR agent.

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

For an OSGi agent (OSGi Agents), org.jolokia.server.core.osgi.OsgiAgentServlet 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 OSGi Agents for details.

This page was built using the Antora default UI. The source code for this UI is licensed under the terms of the MPL-2.0 license. | Copyright © 2010 - 2023 Roland Huß