/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.karaf.management;
import javax.management.openmbean.*;
import java.util.List;
import java.util.Map;
/**
* <p>Security MBean. This MBean can be used to find out whether the currently logged user can access certain MBeans
* or invoke operations on these MBeans. It can be used when building client-facing consoles to ensure that only
* operations appropriate for the current user are presented.</p>
* <p>This MBean does not actually invoke any operations on the given objects, it only checks permissions.</p>
*/
public interface JMXSecurityMBean {
/**
* The Tabular Type returned by the {@link #canInvoke(Map)} operation. The rows consist of
* {@link #CAN_INVOKE_RESULT_ROW_TYPE} entries.
* It has a composite key composed by the "ObjectName" and "Method" columns.
*/
static final TabularType CAN_INVOKE_TABULAR_TYPE = SecurityMBeanOpenTypeInitializer.TABULAR_TYPE;
/**
* A row as returned by the {@link #CAN_INVOKE_TABULAR_TYPE}. The columns of the row are defined
* by {@link #CAN_INVOKE_RESULT_COLUMNS}
*/
static final CompositeType CAN_INVOKE_RESULT_ROW_TYPE = SecurityMBeanOpenTypeInitializer.ROW_TYPE;
/**
* The columns contained in a {@link #CAN_INVOKE_RESULT_ROW_TYPE}. The data types for these columns are
* as follows:
* <ul>
* <li>"ObjectName": {@link SimpleType#STRING}</li>
* <li>"Method": {@link SimpleType#STRING}</li>
* <li>"CanInvoke": {@link SimpleType#BOOLEAN}</li>
* </ul>
*/
static final String[] CAN_INVOKE_RESULT_COLUMNS = SecurityMBeanOpenTypeInitializer.COLUMNS;
/**
* Checks whether the current user can invoke any methods on a JMX MBean.
*
* @param objectName The Object Name of the JMX MBean.
* @return {@code True} if there is at least one method on the MBean that the user can invoke, {@code false} else.
* @throws Exception If the invocation check fails.
*/
boolean canInvoke(String objectName) throws Exception;
/**
* Checks whether the current user can invoke overload of the given method.
*
* @param objectName The Object Name of the JMX MBean.
* @param methodName The name of the method to check.
* @return {@code True} if there is an overload of the specified method that the user can invoke, {@code false} else.
* @throws Exception If the invocation check fails.
*/
boolean canInvoke(String objectName, String methodName) throws Exception;
/**
* Checks whether the current user can invoke the given method.
*
* @param objectName The Object Name of the JMX MBean.
* @param methodName The name of the method to check.
* @param argumentTypes The argument types of the method.
* @return {@code True} if the user is allowed to invoke the method, or any of the methods with the given name if
* {@code null} is used for the arguments. There may still be certain values that the user does not have permissions
* to pass to the method.
* @throws Exception If the invocation check fails.
*/
boolean canInvoke(String objectName, String methodName, String[] argumentTypes) throws Exception;
/**
* Bulk operation to check whether the current user can access the requested MBeans or invoke the requested
* methods.
*
* @param bulkQuery <p>a map of Object Name to requested operations. Operations can be specified with or without
* argument types. An operation without arguments matches any overloaded method with this
* name. If an empty list is provided for the operation names, a check is done whether the
* current user can invoke <em>any</em> operation on the MBean.</p>
* Example:
* <pre>{@code
* Map<String, List<String>> query = new HashMap<>();
* String objectName = "org.acme:type=SomeMBean";
* query.put(objectName, Arrays.asList(
* "testMethod(long,java.lang.String)", // check this testMethod
* "otherMethod")); // check any overload of otherMethod
* query.put("org.acme:type=SomeOtherMBean",
* Collections.<String>emptyList()); // check any method of SomeOtherMBean
* TabularData result = mb.canInvoke(query);
* }</pre>
* @return A Tabular Data object with the result. This object conforms the structure as defined in {@link #CAN_INVOKE_TABULAR_TYPE}
* @throws Exception If the invocation check fails.
*/
TabularData canInvoke(Map<String, List<String>> bulkQuery) throws Exception;
// a member class is used to initialize final fields, as this needs to do some exception handling...
static class SecurityMBeanOpenTypeInitializer {
private static final String[] COLUMNS = new String[]{ "ObjectName", "Method", "CanInvoke" };
private static final CompositeType ROW_TYPE;
static {
try {
ROW_TYPE = new CompositeType("CanInvokeRowType",
"The rows of a CanInvokeTabularType table.",
COLUMNS,
new String[]{
"The ObjectName of the checked MBean.",
"The Method to check. This can be either a bare method name which means 'any method with this name' "
+ "or any specific overload such as foo(java.lang.String). If an empty String is returned this means"
+ " 'any' method.",
"true if the method or MBean can potentially be invoked by the current user."
},
new OpenType[] { SimpleType.STRING, SimpleType.STRING, SimpleType.BOOLEAN });
} catch (OpenDataException e) {
throw new RuntimeException(e);
}
}
private static final TabularType TABULAR_TYPE;
static {
try {
TABULAR_TYPE = new TabularType("CanInvokeTabularType", "Result of canInvoke() bulk operation", ROW_TYPE,
new String[] { "ObjectName", "Method" });
} catch (OpenDataException e) {
throw new RuntimeException(e);
}
}
}
}