Repository: activemq-artemis Updated Branches: refs/heads/2.6.x db818b13e -> da1eeacc0
ARTEMIS-2107 clarify identity for authn failures in notification (cherry picked from commit b86cf69e6a268e08b43f857656f3b849e06e0ea4) Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/da1eeacc Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/da1eeacc Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/da1eeacc Branch: refs/heads/2.6.x Commit: da1eeacc0d8b963cae9e61a1b5b9c207a1af4cac Parents: db818b1 Author: Justin Bertram <[email protected]> Authored: Wed Oct 3 13:03:18 2018 -0500 Committer: Justin Bertram <[email protected]> Committed: Thu Oct 11 16:55:06 2018 -0500 ---------------------------------------------------------------------- .../api/core/management/ManagementHelper.java | 2 + .../core/security/impl/SecurityStoreImpl.java | 15 +- docs/user-manual/en/management.md | 2 +- .../management/SSLSecurityNotificationTest.java | 181 +++++++++++++++++++ .../management/SecurityNotificationTest.java | 3 + .../src/test/resources/cert-roles.properties | 1 + 6 files changed, 197 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/da1eeacc/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ManagementHelper.java ---------------------------------------------------------------------- diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ManagementHelper.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ManagementHelper.java index a682eba..7b6d3ff 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ManagementHelper.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ManagementHelper.java @@ -62,6 +62,8 @@ public final class ManagementHelper { public static final SimpleString HDR_USER = new SimpleString("_AMQ_User"); + public static final SimpleString HDR_CERT_SUBJECT_DN = new SimpleString("_AMQ_CertSubjectDN"); + public static final SimpleString HDR_CHECK_TYPE = new SimpleString("_AMQ_CheckType"); public static final SimpleString HDR_SESSION_NAME = new SimpleString("_AMQ_SessionName"); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/da1eeacc/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java index a690954..761a20b 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java @@ -140,20 +140,23 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC } if (!userIsValid && validatedUser == null) { + String certSubjectDN = "unavailable"; + X509Certificate[] certs = CertificateUtil.getCertsFromConnection(connection); + if (certs != null && certs.length > 0 && certs[0] != null) { + certSubjectDN = certs[0].getSubjectDN().getName(); + } + if (notificationService != null) { TypedProperties props = new TypedProperties(); + props.putSimpleStringProperty(ManagementHelper.HDR_USER, SimpleString.toSimpleString(user)); + props.putSimpleStringProperty(ManagementHelper.HDR_CERT_SUBJECT_DN, SimpleString.toSimpleString(certSubjectDN)); + props.putSimpleStringProperty(ManagementHelper.HDR_REMOTE_ADDRESS, SimpleString.toSimpleString(connection.getRemoteAddress())); Notification notification = new Notification(null, CoreNotificationType.SECURITY_AUTHENTICATION_VIOLATION, props); notificationService.sendNotification(notification); } - String certSubjectDN = "unavailable"; - X509Certificate[] certs = CertificateUtil.getCertsFromConnection(connection); - if (certs != null && certs.length > 0 && certs[0] != null) { - certSubjectDN = certs[0].getSubjectDN().getName(); - } - throw ActiveMQMessageBundle.BUNDLE.unableToValidateUser(connection.getRemoteAddress(), user, certSubjectDN); } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/da1eeacc/docs/user-manual/en/management.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/management.md b/docs/user-manual/en/management.md index d415e98..350f7e6 100644 --- a/docs/user-manual/en/management.md +++ b/docs/user-manual/en/management.md @@ -746,7 +746,7 @@ un-formatted result of a call to `java.lang.System.currentTimeMillis()`. - `SECURITY_AUTHENTICATION_VIOLATION` (6) - `_AMQ_User` + `_AMQ_User`, `_AMQ_CertSubjectDN`, `_AMQ_RemoteAddress` - `SECURITY_PERMISSION_VIOLATION` (7) http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/da1eeacc/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/SSLSecurityNotificationTest.java ---------------------------------------------------------------------- diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/SSLSecurityNotificationTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/SSLSecurityNotificationTest.java new file mode 100644 index 0000000..26e0cca --- /dev/null +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/SSLSecurityNotificationTest.java @@ -0,0 +1,181 @@ +/* + * 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.integration.management; + +import java.lang.management.ManagementFactory; +import java.net.URL; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration; +import org.apache.activemq.artemis.api.core.ActiveMQException; +import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.api.core.TransportConfiguration; +import org.apache.activemq.artemis.api.core.client.ActiveMQClient; +import org.apache.activemq.artemis.api.core.client.ClientConsumer; +import org.apache.activemq.artemis.api.core.client.ClientMessage; +import org.apache.activemq.artemis.api.core.client.ClientSession; +import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; +import org.apache.activemq.artemis.api.core.client.ServerLocator; +import org.apache.activemq.artemis.api.core.management.ManagementHelper; +import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants; +import org.apache.activemq.artemis.core.security.Role; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.ActiveMQServers; +import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager; +import org.apache.activemq.artemis.tests.integration.security.SecurityTest; +import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; +import org.apache.activemq.artemis.utils.RandomUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.apache.activemq.artemis.api.core.management.CoreNotificationType.SECURITY_AUTHENTICATION_VIOLATION; + +public class SSLSecurityNotificationTest extends ActiveMQTestBase { + + static { + String path = System.getProperty("java.security.auth.login.config"); + if (path == null) { + URL resource = SecurityTest.class.getClassLoader().getResource("login.config"); + if (resource != null) { + path = resource.getFile(); + System.setProperty("java.security.auth.login.config", path); + } + } + } + + private ActiveMQServer server; + + private ClientSession adminSession; + + private ClientConsumer notifConsumer; + + private SimpleString notifQueue; + + @Test + public void testSECURITY_AUTHENTICATION_VIOLATION() throws Exception { + SSLSecurityNotificationTest.flush(notifConsumer); + + TransportConfiguration tc = new TransportConfiguration(NETTY_CONNECTOR_FACTORY); + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "client-side-truststore.jks"); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, "secureexample"); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "bad-client-side-keystore.jks"); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, "secureexample"); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator)); + + try { + sf.createSession(); + Assert.fail("authentication must fail and a notification of security violation must be sent"); + } catch (Exception e) { + } + + ClientMessage[] notifications = SSLSecurityNotificationTest.consumeMessages(1, notifConsumer); + Assert.assertEquals(SECURITY_AUTHENTICATION_VIOLATION.toString(), notifications[0].getObjectProperty(ManagementHelper.HDR_NOTIFICATION_TYPE).toString()); + Assert.assertEquals(null, notifications[0].getObjectProperty(ManagementHelper.HDR_USER)); + Assert.assertEquals("CN=Bad Client, OU=Artemis, O=ActiveMQ, L=AMQ, ST=AMQ, C=AMQ", notifications[0].getObjectProperty(ManagementHelper.HDR_CERT_SUBJECT_DN).toString()); + Assert.assertTrue(notifications[0].getObjectProperty(ManagementHelper.HDR_REMOTE_ADDRESS).toString().startsWith("/127.0.0.1")); + } + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + ActiveMQJAASSecurityManager securityManager = new ActiveMQJAASSecurityManager("CertLogin"); + server = addServer(ActiveMQServers.newActiveMQServer(createDefaultInVMConfig().setSecurityEnabled(true), ManagementFactory.getPlatformMBeanServer(), securityManager, false)); + + Map<String, Object> params = new HashMap<>(); + params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "server-side-keystore.jks"); + params.put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, "secureexample"); + params.put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "server-side-truststore.jks"); + params.put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, "secureexample"); + params.put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + + server.getConfiguration().addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params)); + + server.start(); + + notifQueue = RandomUtil.randomSimpleString(); + + Role role = new Role("notif", true, true, true, true, true, true, true, true, true, true); + Set<Role> roles = new HashSet<>(); + roles.add(role); + server.getSecurityRepository().addMatch(ActiveMQDefaultConfiguration.getDefaultManagementNotificationAddress().toString(), roles); + + TransportConfiguration tc = new TransportConfiguration(NETTY_CONNECTOR_FACTORY); + tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "client-side-truststore.jks"); + tc.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, "secureexample"); + tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "client-side-keystore.jks"); + tc.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, "secureexample"); + + ServerLocator locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc)); + ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator)); + adminSession = sf.createSession(true, true, 1); + adminSession.start(); + + adminSession.createTemporaryQueue(ActiveMQDefaultConfiguration.getDefaultManagementNotificationAddress(), notifQueue); + + notifConsumer = adminSession.createConsumer(notifQueue); + } + + // Private ------------------------------------------------------- + + private static void flush(final ClientConsumer notifConsumer) throws ActiveMQException { + ClientMessage message = null; + do { + message = notifConsumer.receive(500); + } + while (message != null); + } + + protected static ClientMessage[] consumeMessages(final int expected, + final ClientConsumer consumer) throws Exception { + ClientMessage[] messages = new ClientMessage[expected]; + + ClientMessage m = null; + for (int i = 0; i < expected; i++) { + m = consumer.receive(500); + if (m != null) { + for (SimpleString key : m.getPropertyNames()) { + System.out.println(key + "=" + m.getObjectProperty(key)); + } + } + Assert.assertNotNull("expected to received " + expected + " messages, got only " + i, m); + messages[i] = m; + m.acknowledge(); + } + m = consumer.receiveImmediate(); + if (m != null) { + for (SimpleString key : m.getPropertyNames()) { + System.out.println(key + "=" + m.getObjectProperty(key)); + } + } + Assert.assertNull("received one more message than expected (" + expected + ")", m); + + return messages; + } + + // Inner classes ------------------------------------------------- + +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/da1eeacc/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/SecurityNotificationTest.java ---------------------------------------------------------------------- diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/SecurityNotificationTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/SecurityNotificationTest.java index 13208fc..579811a 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/SecurityNotificationTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/SecurityNotificationTest.java @@ -80,6 +80,9 @@ public class SecurityNotificationTest extends ActiveMQTestBase { ClientMessage[] notifications = SecurityNotificationTest.consumeMessages(1, notifConsumer); Assert.assertEquals(SECURITY_AUTHENTICATION_VIOLATION.toString(), notifications[0].getObjectProperty(ManagementHelper.HDR_NOTIFICATION_TYPE).toString()); + Assert.assertEquals(unknownUser, notifications[0].getObjectProperty(ManagementHelper.HDR_USER).toString()); + Assert.assertEquals("unavailable", notifications[0].getObjectProperty(ManagementHelper.HDR_CERT_SUBJECT_DN).toString()); + Assert.assertEquals("invm:0", notifications[0].getObjectProperty(ManagementHelper.HDR_REMOTE_ADDRESS).toString()); } @Test http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/da1eeacc/tests/integration-tests/src/test/resources/cert-roles.properties ---------------------------------------------------------------------- diff --git a/tests/integration-tests/src/test/resources/cert-roles.properties b/tests/integration-tests/src/test/resources/cert-roles.properties index 5f860fc..6ca5d99 100644 --- a/tests/integration-tests/src/test/resources/cert-roles.properties +++ b/tests/integration-tests/src/test/resources/cert-roles.properties @@ -17,3 +17,4 @@ programmers=first widgets=second +notif=first
