[prev in list] [next in list] [prev in thread] [next in thread]
List: activemq-commits
Subject: [activemq-artemis] branch master updated: ARTEMIS-3014 Fix JMX RBAC guard
From: jbertram () apache ! org
Date: 2020-11-30 17:12:43
Message-ID: 160675636347.947.17560243313932091087 () gitbox ! apache ! org
[Download RAW message or body]
This is an automated email from the ASF dual-hosted git repository.
jbertram pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git
The following commit(s) were added to refs/heads/master by this push:
new 7eb22c1 ARTEMIS-3014 Fix JMX RBAC guard
new f64dfea This closes #3364
7eb22c1 is described below
commit 7eb22c18db4bd81ef79c619173579cb54442fa9e
Author: Domenico Francesco Bruscino <brusdev@apache.org>
AuthorDate: Sat Nov 28 23:10:05 2020 +0100
ARTEMIS-3014 Fix JMX RBAC guard
---
.../artemis/cli/factory/jmx/ManagementFactory.java | 2 +
.../apache/activemq/artemis/util/ServerUtil.java | 12 +-
.../core/server/management/ManagementContext.java | 18 +--
tests/smoke-tests/pom.xml | 20 +++
.../main/resources/servers/jmx-rbac/management.xml | 52 ++++++++
.../artemis/tests/smoke/jmxrbac/JmxRBACTest.java | 137 +++++++++++++++++++++
6 files changed, 231 insertions(+), 10 deletions(-)
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/jmx/ManagementFactory.java \
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/jmx/ManagementFactory.java
index 826dc8e..b41a1ef 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/jmx/ManagementFactory.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/jmx/ManagementFactory.java
@@ -134,6 +134,8 @@ public class ManagementFactory {
context.setSecurityManager(securityManager);
}
+ context.init();
+
return context;
}
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/util/ServerUtil.java \
b/artemis-cli/src/main/java/org/apache/activemq/artemis/util/ServerUtil.java index \
7c8675b..6d7cf8f 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/util/ServerUtil.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/util/ServerUtil.java
@@ -105,14 +105,22 @@ public class ServerUtil {
}
public static boolean waitForServerToStart(int id, int timeout) throws \
InterruptedException {
- return waitForServerToStart("tcp://localhost:" + (61616 + id), timeout);
+ return waitForServerToStart(id, null, null, timeout);
+ }
+
+ public static boolean waitForServerToStart(int id, String username, String \
password, int timeout) throws InterruptedException { + return \
waitForServerToStart("tcp://localhost:" + (61616 + id), username, password, timeout); \
}
public static boolean waitForServerToStart(String uri, long timeout) throws \
InterruptedException { + return waitForServerToStart(uri, null, null, timeout);
+ }
+
+ public static boolean waitForServerToStart(String uri, String username, String \
password, long timeout) throws InterruptedException { long realTimeout = \
System.currentTimeMillis() + timeout; while (System.currentTimeMillis() < \
realTimeout) {
try (ActiveMQConnectionFactory cf = \
ActiveMQJMSClient.createConnectionFactory(uri, null)) {
- cf.createConnection().close();
+ cf.createConnection(username, password).close();
System.out.println("server " + uri + " started");
} catch (Exception e) {
System.out.println("awaiting server " + uri + " start at ");
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ManagementContext.java \
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ManagementContext.java
index f518c2d..db308ac 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ManagementContext.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ManagementContext.java
@@ -34,6 +34,16 @@ public class ManagementContext implements ServiceComponent {
private ArtemisMBeanServerGuard guardHandler;
private ActiveMQSecurityManager securityManager;
+ public void init() {
+ if (accessControlList != null) {
+ //if we are configured then assume we want to use the guard so set the \
system property + System.setProperty("javax.management.builder.initial", \
ArtemisMBeanServerBuilder.class.getCanonicalName()); + guardHandler = new \
ArtemisMBeanServerGuard(); + \
guardHandler.setJMXAccessControlList(accessControlList); + \
ArtemisMBeanServerBuilder.setGuard(guardHandler); + }
+ }
+
@Override
public void start() throws Exception {
if (isStarted) {
@@ -44,14 +54,6 @@ public class ManagementContext implements ServiceComponent {
return;
}
isStarted = true;
- if (accessControlList != null) {
- //if we are configured then assume we want to use the guard so set the \
system property
- System.setProperty("javax.management.builder.initial", \
ArtemisMBeanServerBuilder.class.getCanonicalName());
- guardHandler = new ArtemisMBeanServerGuard();
- guardHandler.setJMXAccessControlList(accessControlList);
- ArtemisMBeanServerBuilder.setGuard(guardHandler);
- }
-
if (jmxConnectorConfiguration != null) {
mBeanServer = new ManagementConnector(jmxConnectorConfiguration, \
securityManager); mBeanServer.start();
diff --git a/tests/smoke-tests/pom.xml b/tests/smoke-tests/pom.xml
index 5bf24ce..3c5bd43 100644
--- a/tests/smoke-tests/pom.xml
+++ b/tests/smoke-tests/pom.xml
@@ -406,6 +406,26 @@
</execution>
<execution>
<phase>test-compile</phase>
+ <id>create-createJMXRBAC</id>
+ <goals>
+ <goal>create</goal>
+ </goals>
+ <configuration>
+ <role>amq</role>
+ <user>admin</user>
+ <password>admin</password>
+ <allowAnonymous>false</allowAnonymous>
+ <instance>${basedir}/target/jmx-rbac</instance>
+ \
<configuration>${basedir}/target/classes/servers/jmx-rbac</configuration> + \
<args> + <!-- this is needed to run the server remotely -->
+ <arg>--java-options</arg>
+ <arg>-Djava.rmi.server.hostname=localhost</arg>
+ </args>
+ </configuration>
+ </execution>
+ <execution>
+ <phase>test-compile</phase>
<id>create-createAuditLogging</id>
<goals>
<goal>create</goal>
diff --git a/tests/smoke-tests/src/main/resources/servers/jmx-rbac/management.xml \
b/tests/smoke-tests/src/main/resources/servers/jmx-rbac/management.xml new file mode \
100644 index 0000000..44e491e
--- /dev/null
+++ b/tests/smoke-tests/src/main/resources/servers/jmx-rbac/management.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ 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.
+ -->
+<management-context xmlns="http://activemq.org/schema">
+ <connector connector-port="10099"/>
+ <authorisation>
+ <whitelist>
+ <entry domain="hawtio"/>
+ </whitelist>
+ <default-access>
+ <access method="list*" roles="amq"/>
+ <access method="get*" roles="amq"/>
+ <access method="is*" roles="amq"/>
+ <access method="set*" roles="amq"/>
+ <access method="*" roles="amq"/>
+ </default-access>
+ <role-access>
+ <match domain="java.lang" key="type=Memory">
+ <access method="gc" roles="amq-user"/>
+ </match>
+ <match domain="org.apache.activemq.artemis">
+ <access method="list*" roles="amq"/>
+ <access method="get*" roles="amq"/>
+ <access method="is*" roles="amq"/>
+ <access method="set*" roles="amq"/>
+ <access method="*" roles="amq"/>
+ </match>
+ <!--example of how to configure a specific object-->
+ <!--<match domain="org.apache.activemq.artemis" key="subcomponent=queues">
+ <access method="list*" roles="view,update,amq"/>
+ <access method="get*" roles="view,update,amq"/>
+ <access method="is*" roles="view,update,amq"/>
+ <access method="set*" roles="update,amq"/>
+ <access method="*" roles="amq"/>
+ </match>-->
+ </role-access>
+ </authorisation>
+</management-context>
\ No newline at end of file
diff --git a/tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/jmxrbac/JmxRBACTest.java \
b/tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/jmxrbac/JmxRBACTest.java
new file mode 100644
index 0000000..c25eced
--- /dev/null
+++ b/tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/jmxrbac/JmxRBACTest.java
@@ -0,0 +1,137 @@
+/**
+ * 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.activemq.artemis.tests.smoke.jmxrbac;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+import java.util.Collections;
+
+import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
+import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl;
+import org.apache.activemq.artemis.api.core.management.ObjectNameBuilder;
+import org.apache.activemq.artemis.tests.smoke.common.SmokeTestBase;
+import org.apache.activemq.artemis.util.ServerUtil;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JmxRBACTest extends SmokeTestBase {
+ // This test will use a smoke created by the pom on this project (smoke-tsts)
+
+ private static final String JMX_SERVER_HOSTNAME = "localhost";
+ private static final int JMX_SERVER_PORT = 10099;
+
+ public static final String SERVER_NAME_0 = "jmx-rbac";
+
+ public static final String SERVER_ADMIN = "admin";
+ public static final String SERVER_USER = "user";
+
+
+ @Before
+ public void before() throws Exception {
+ cleanupData(SERVER_NAME_0);
+ disableCheckThread();
+ startServer(SERVER_NAME_0, 0, 0);
+ ServerUtil.waitForServerToStart(0, SERVER_ADMIN, SERVER_ADMIN, 30000);
+ }
+
+ @Test
+ public void testManagementRoleAccess() throws Exception {
+ // Without this, the RMI server would bind to the default interface IP (the \
user's local IP mostly) + System.setProperty("java.rmi.server.hostname", \
JMX_SERVER_HOSTNAME); +
+ // I don't specify both ports here manually on purpose. See actual RMI \
registry connection port extraction below. + String urlString = \
"service:jmx:rmi:///jndi/rmi://" + JMX_SERVER_HOSTNAME + ":" + JMX_SERVER_PORT + \
"/jmxrmi"; +
+ JMXServiceURL url = new JMXServiceURL(urlString);
+ JMXConnector jmxConnector;
+
+ try {
+ //Connect using the admin.
+ jmxConnector = JMXConnectorFactory.connect(url, Collections.singletonMap(
+ "jmx.remote.credentials", new String[] {SERVER_ADMIN, SERVER_ADMIN}));
+ System.out.println("Successfully connected to: " + urlString);
+ } catch (Exception e) {
+ jmxConnector = null;
+ e.printStackTrace();
+ Assert.fail(e.getMessage());
+ }
+
+ try {
+ //Create an user.
+ MBeanServerConnection mBeanServerConnection = \
jmxConnector.getMBeanServerConnection(); + String brokerName = "0.0.0.0"; // \
configured e.g. in broker.xml <broker-name> element + ObjectNameBuilder \
objectNameBuilder = ObjectNameBuilder.create(ActiveMQDefaultConfiguration.getDefaultJmxDomain(), \
brokerName, true); + ActiveMQServerControl activeMQServerControl = \
MBeanServerInvocationHandler.newProxyInstance(mBeanServerConnection, \
objectNameBuilder.getActiveMQServerObjectName(), ActiveMQServerControl.class, false); \
+ ObjectName memoryObjectName = new ObjectName("java.lang:type=Memory"); +
+ try {
+ activeMQServerControl.removeUser(SERVER_USER);
+ } catch (Exception ignore) {
+ }
+ activeMQServerControl.addUser(SERVER_USER, SERVER_USER, "amq-user", true);
+
+ activeMQServerControl.getVersion();
+
+ try {
+ mBeanServerConnection.invoke(memoryObjectName, "gc", null, null);
+ Assert.fail(SERVER_ADMIN + " should not access to " + memoryObjectName);
+ } catch (Exception e) {
+ Assert.assertEquals(SecurityException.class, e.getClass());
+ }
+ } finally {
+ jmxConnector.close();
+ }
+
+ try {
+ //Connect using an user.
+ jmxConnector = JMXConnectorFactory.connect(url, Collections.singletonMap(
+ "jmx.remote.credentials", new String[] {SERVER_USER, SERVER_USER}));
+ System.out.println("Successfully connected to: " + urlString);
+ } catch (Exception e) {
+ jmxConnector = null;
+ e.printStackTrace();
+ Assert.fail(e.getMessage());
+ }
+
+
+ try {
+ MBeanServerConnection mBeanServerConnection = \
jmxConnector.getMBeanServerConnection(); + String brokerName = "0.0.0.0"; // \
configured e.g. in broker.xml <broker-name> element + ObjectNameBuilder \
objectNameBuilder = ObjectNameBuilder.create(ActiveMQDefaultConfiguration.getDefaultJmxDomain(), \
brokerName, true); + ActiveMQServerControl activeMQServerControl = \
MBeanServerInvocationHandler.newProxyInstance(mBeanServerConnection, \
objectNameBuilder.getActiveMQServerObjectName(), ActiveMQServerControl.class, false); \
+ ObjectName memoryObjectName = new ObjectName("java.lang:type=Memory"); +
+ mBeanServerConnection.invoke(memoryObjectName, "gc", null, null);
+
+ try {
+ activeMQServerControl.getVersion();
+ Assert.fail(SERVER_USER + " should not access to " + \
objectNameBuilder.getActiveMQServerObjectName()); + } catch (Exception e) {
+ Assert.assertEquals(SecurityException.class, e.getClass());
+ }
+ } finally {
+ jmxConnector.close();
+ }
+ }
+}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic