This closes #2917
This commit is contained in:
commit
c2eb037919
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.cli.factory.security;
|
||||||
|
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.dto.SecurityManagerDTO;
|
||||||
|
import org.apache.activemq.artemis.dto.PropertyDTO;
|
||||||
|
import org.apache.activemq.artemis.dto.SecurityDTO;
|
||||||
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
|
||||||
|
import org.apache.activemq.artemis.utils.ClassloadingUtil;
|
||||||
|
|
||||||
|
public class SecurityManagerHandler implements SecurityHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActiveMQSecurityManager createSecurityManager(SecurityDTO security) {
|
||||||
|
SecurityManagerDTO customSecurity = (SecurityManagerDTO) security;
|
||||||
|
String clazz = customSecurity.className;
|
||||||
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
for (PropertyDTO property : customSecurity.properties) {
|
||||||
|
properties.put(property.key, property.value);
|
||||||
|
}
|
||||||
|
return AccessController.doPrivileged((PrivilegedAction<ActiveMQSecurityManager>) () -> (ActiveMQSecurityManager) ClassloadingUtil.newInstanceFromClassLoader(SecurityManagerHandler.class, clazz)).init(properties);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
## ---------------------------------------------------------------------------
|
||||||
|
## 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.
|
||||||
|
## ---------------------------------------------------------------------------
|
||||||
|
class=org.apache.activemq.artemis.cli.factory.security.SecurityManagerHandler
|
|
@ -28,6 +28,10 @@ import javax.json.JsonObject;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.transform.Transformer;
|
||||||
|
import javax.xml.transform.TransformerFactory;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -43,6 +47,8 @@ import org.apache.activemq.artemis.api.core.JsonUtil;
|
||||||
import org.apache.activemq.artemis.api.core.Pair;
|
import org.apache.activemq.artemis.api.core.Pair;
|
||||||
import org.apache.activemq.artemis.api.core.RoutingType;
|
import org.apache.activemq.artemis.api.core.RoutingType;
|
||||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||||
|
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
|
||||||
|
import org.apache.activemq.artemis.api.core.client.ClientProducer;
|
||||||
import org.apache.activemq.artemis.api.core.client.ClientSession;
|
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.ClientSessionFactory;
|
||||||
import org.apache.activemq.artemis.api.core.client.ServerLocator;
|
import org.apache.activemq.artemis.api.core.client.ServerLocator;
|
||||||
|
@ -62,12 +68,13 @@ import org.apache.activemq.artemis.cli.commands.util.SyncCalculation;
|
||||||
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
|
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
|
||||||
import org.apache.activemq.artemis.core.config.FileDeploymentManager;
|
import org.apache.activemq.artemis.core.config.FileDeploymentManager;
|
||||||
import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
|
import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
|
||||||
|
import org.apache.activemq.artemis.core.security.CheckType;
|
||||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||||
import org.apache.activemq.artemis.core.server.JournalType;
|
import org.apache.activemq.artemis.core.server.JournalType;
|
||||||
import org.apache.activemq.artemis.core.server.management.ManagementContext;
|
import org.apache.activemq.artemis.core.server.management.ManagementContext;
|
||||||
import org.apache.activemq.artemis.nativo.jlibaio.LibaioContext;
|
|
||||||
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
|
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
|
||||||
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
|
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
|
||||||
|
import org.apache.activemq.artemis.nativo.jlibaio.LibaioContext;
|
||||||
import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;
|
import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;
|
||||||
import org.apache.activemq.artemis.utils.HashProcessor;
|
import org.apache.activemq.artemis.utils.HashProcessor;
|
||||||
import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
|
import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
|
||||||
|
@ -81,6 +88,8 @@ import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -235,6 +244,84 @@ public class ArtemisTest extends CliTestBase {
|
||||||
assertEquals("password2", trustPass);
|
assertEquals("password2", trustPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSecurityManagerConfiguration() throws Exception {
|
||||||
|
setupAuth();
|
||||||
|
Run.setEmbedded(true);
|
||||||
|
File instance1 = new File(temporaryFolder.getRoot(), "instance1");
|
||||||
|
Artemis.main("create", instance1.getAbsolutePath(), "--silent", "--no-fsync", "--no-autotune", "--no-web", "--no-stomp-acceptor", "--no-amqp-acceptor", "--no-mqtt-acceptor", "--no-hornetq-acceptor");
|
||||||
|
File originalBootstrapFile = new File(new File(instance1, "etc"), "bootstrap.xml");
|
||||||
|
assertTrue(originalBootstrapFile.exists());
|
||||||
|
|
||||||
|
// modify the XML programmatically since we don't support setting this stuff via the CLI
|
||||||
|
Document config = parseXml(originalBootstrapFile);
|
||||||
|
Node broker = config.getChildNodes().item(1);
|
||||||
|
NodeList list = broker.getChildNodes();
|
||||||
|
Node server = null;
|
||||||
|
|
||||||
|
for (int i = 0; i < list.getLength(); i++) {
|
||||||
|
Node node = list.item(i);
|
||||||
|
if ("jaas-security".equals(node.getNodeName())) {
|
||||||
|
// get rid of the default jaas-security config
|
||||||
|
broker.removeChild(node);
|
||||||
|
}
|
||||||
|
if ("server".equals(node.getNodeName())) {
|
||||||
|
server = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the new security-plugin config
|
||||||
|
Element securityPluginElement = config.createElement("security-manager");
|
||||||
|
securityPluginElement.setAttribute("class-name", TestSecurityManager.class.getName());
|
||||||
|
Element property1 = config.createElement("property");
|
||||||
|
property1.setAttribute("key", "myKey1");
|
||||||
|
property1.setAttribute("value", "myValue1");
|
||||||
|
securityPluginElement.appendChild(property1);
|
||||||
|
Element property2 = config.createElement("property");
|
||||||
|
property2.setAttribute("key", "myKey2");
|
||||||
|
property2.setAttribute("value", "myValue2");
|
||||||
|
securityPluginElement.appendChild(property2);
|
||||||
|
broker.insertBefore(securityPluginElement, server);
|
||||||
|
|
||||||
|
originalBootstrapFile.delete();
|
||||||
|
|
||||||
|
// write the modified config into the bootstrap.xml file
|
||||||
|
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
|
Transformer transformer = transformerFactory.newTransformer();
|
||||||
|
DOMSource source = new DOMSource(config);
|
||||||
|
StreamResult streamResult = new StreamResult(originalBootstrapFile);
|
||||||
|
transformer.transform(source, streamResult);
|
||||||
|
|
||||||
|
System.setProperty("artemis.instance", instance1.getAbsolutePath());
|
||||||
|
Object result = Artemis.internalExecute("run");
|
||||||
|
ActiveMQServer activeMQServer = ((Pair<ManagementContext, ActiveMQServer>)result).getB();
|
||||||
|
|
||||||
|
// trigger security
|
||||||
|
ServerLocator locator = ActiveMQClient.createServerLocator("tcp://127.0.0.1:61616");
|
||||||
|
ClientSessionFactory sessionFactory = locator.createSessionFactory();
|
||||||
|
ClientSession session = sessionFactory.createSession("myUser", "myPass", false, true, true, false, 0);
|
||||||
|
ClientProducer producer = session.createProducer("foo");
|
||||||
|
producer.send(session.createMessage(true));
|
||||||
|
|
||||||
|
// verify results
|
||||||
|
assertTrue(activeMQServer.getSecurityManager() instanceof TestSecurityManager);
|
||||||
|
TestSecurityManager securityPlugin = (TestSecurityManager) activeMQServer.getSecurityManager();
|
||||||
|
assertTrue(securityPlugin.properties.containsKey("myKey1"));
|
||||||
|
assertEquals("myValue1", securityPlugin.properties.get("myKey1"));
|
||||||
|
assertTrue(securityPlugin.properties.containsKey("myKey2"));
|
||||||
|
assertEquals("myValue2", securityPlugin.properties.get("myKey2"));
|
||||||
|
assertTrue(securityPlugin.validateUser);
|
||||||
|
assertEquals("myUser", securityPlugin.validateUserName);
|
||||||
|
assertEquals("myPass", securityPlugin.validateUserPass);
|
||||||
|
assertTrue(securityPlugin.validateUserAndRole);
|
||||||
|
assertEquals("myUser", securityPlugin.validateUserAndRoleName);
|
||||||
|
assertEquals("myPass", securityPlugin.validateUserAndRolePass);
|
||||||
|
assertEquals(CheckType.SEND, securityPlugin.checkType);
|
||||||
|
|
||||||
|
activeMQServer.stop();
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStopManagementContext() throws Exception {
|
public void testStopManagementContext() throws Exception {
|
||||||
Run.setEmbedded(true);
|
Run.setEmbedded(true);
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* 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.cli.test;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.core.security.CheckType;
|
||||||
|
import org.apache.activemq.artemis.core.security.Role;
|
||||||
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a simple *test* security manager used to verify configuration via bootstrap.xml.
|
||||||
|
*/
|
||||||
|
public class TestSecurityManager implements ActiveMQSecurityManager {
|
||||||
|
public Map<String, String> properties;
|
||||||
|
public boolean validateUser = false;
|
||||||
|
public String validateUserName;
|
||||||
|
public String validateUserPass;
|
||||||
|
public boolean validateUserAndRole = false;
|
||||||
|
public String validateUserAndRoleName;
|
||||||
|
public String validateUserAndRolePass;
|
||||||
|
public CheckType checkType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validateUser(String user, String password) {
|
||||||
|
this.validateUser = true;
|
||||||
|
this.validateUserName = user;
|
||||||
|
this.validateUserPass = password;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validateUserAndRole(String user, String password, Set<Role> roles, CheckType checkType) {
|
||||||
|
this.validateUserAndRole = true;
|
||||||
|
this.validateUserAndRoleName = user;
|
||||||
|
this.validateUserAndRolePass = password;
|
||||||
|
this.checkType = checkType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActiveMQSecurityManager init(Map<String, String> properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,6 +81,7 @@ cd rest; mvn verify; cd ..
|
||||||
cd scheduled-message; mvn verify; cd ..
|
cd scheduled-message; mvn verify; cd ..
|
||||||
cd security; mvn verify; cd ..
|
cd security; mvn verify; cd ..
|
||||||
cd security-ldap; mvn verify; cd ..
|
cd security-ldap; mvn verify; cd ..
|
||||||
|
cd security-manager; mvn verify; cd ..
|
||||||
cd send-acknowledgements; mvn verify; cd ..
|
cd send-acknowledgements; mvn verify; cd ..
|
||||||
cd shared-consumer; mvn verify; cd ..
|
cd shared-consumer; mvn verify; cd ..
|
||||||
cd slow-consumer; mvn verify; cd ..
|
cd slow-consumer; mvn verify; cd ..
|
||||||
|
|
|
@ -80,6 +80,7 @@ cd rest; mvn verify; cd ..
|
||||||
cd scheduled-message; mvn verify; cd ..
|
cd scheduled-message; mvn verify; cd ..
|
||||||
cd security; mvn verify; cd ..
|
cd security; mvn verify; cd ..
|
||||||
cd security-ldap; mvn verify; cd ..
|
cd security-ldap; mvn verify; cd ..
|
||||||
|
cd security-manager; mvn verify; cd ..
|
||||||
cd send-acknowledgements; mvn verify; cd ..
|
cd send-acknowledgements; mvn verify; cd ..
|
||||||
cd shared-consumer; mvn verify; cd ..
|
cd shared-consumer; mvn verify; cd ..
|
||||||
cd slow-consumer; mvn verify; cd ..
|
cd slow-consumer; mvn verify; cd ..
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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.dto;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
@XmlRootElement(name = "property")
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
public class PropertyDTO {
|
||||||
|
|
||||||
|
@XmlAttribute
|
||||||
|
public String key;
|
||||||
|
|
||||||
|
@XmlAttribute
|
||||||
|
public String value;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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.dto;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
import javax.xml.bind.annotation.XmlElementRef;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@XmlRootElement(name = "security-manager")
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
public class SecurityManagerDTO extends SecurityDTO {
|
||||||
|
|
||||||
|
@XmlAttribute(name = "class-name", required = true)
|
||||||
|
public String className;
|
||||||
|
|
||||||
|
@XmlElementRef
|
||||||
|
public List<PropertyDTO> properties;
|
||||||
|
}
|
|
@ -17,5 +17,6 @@
|
||||||
BrokerDTO
|
BrokerDTO
|
||||||
SecurityDTO
|
SecurityDTO
|
||||||
JaasSecurityDTO
|
JaasSecurityDTO
|
||||||
|
SecurityManagerDTO
|
||||||
ManagementContextDTO
|
ManagementContextDTO
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.artemis.spi.core.security;
|
package org.apache.activemq.artemis.spi.core.security;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.activemq.artemis.core.security.CheckType;
|
import org.apache.activemq.artemis.core.security.CheckType;
|
||||||
|
@ -50,4 +51,16 @@ public interface ActiveMQSecurityManager {
|
||||||
* @return true if the user is valid and they have the correct roles
|
* @return true if the user is valid and they have the correct roles
|
||||||
*/
|
*/
|
||||||
boolean validateUserAndRole(String user, String password, Set<Role> roles, CheckType checkType);
|
boolean validateUserAndRole(String user, String password, Set<Role> roles, CheckType checkType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the manager with the given configuration properties. This method is called by the broker when the
|
||||||
|
* file-based configuration is read. If you're creating/configuring the plugin programmatically then the
|
||||||
|
* recommended approach is to simply use the manager's getters/setters rather than this method.
|
||||||
|
*
|
||||||
|
* @param properties name/value pairs used to configure the ActiveMQSecurityManager instance
|
||||||
|
* @return {@code this} instance
|
||||||
|
*/
|
||||||
|
default ActiveMQSecurityManager init(Map<String, String> properties) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
# Security
|
# Security
|
||||||
|
|
||||||
This chapter describes how security works with Apache ActiveMQ Artemis and how
|
This chapter describes how security works with Apache ActiveMQ Artemis and how
|
||||||
you can configure it. To disable security completely simply set the
|
you can configure it.
|
||||||
`security-enabled` property to false in the `broker.xml` file.
|
|
||||||
|
To disable security completely simply set the `security-enabled` property to
|
||||||
|
`false` in the `broker.xml` file.
|
||||||
|
|
||||||
For performance reasons security is cached and invalidated every so long. To
|
For performance reasons security is cached and invalidated every so long. To
|
||||||
change this period set the property `security-invalidation-interval`, which is
|
change this period set the property `security-invalidation-interval`, which is
|
||||||
|
@ -1202,3 +1204,27 @@ The param-value for each list is a comma separated string value representing the
|
||||||
|
|
||||||
For details about masking passwords in broker.xml please see the [Masking
|
For details about masking passwords in broker.xml please see the [Masking
|
||||||
Passwords](masking-passwords.md) chapter.
|
Passwords](masking-passwords.md) chapter.
|
||||||
|
|
||||||
|
## Custom Security Manager
|
||||||
|
|
||||||
|
The underpinnings of the broker's security implementation can be changed if so
|
||||||
|
desired. The broker uses a component called a "security manager" to implement
|
||||||
|
the actual authentication and authorization checks. By default, the broker uses
|
||||||
|
`org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager` to
|
||||||
|
provide JAAS integration, but users can provide their own implementation of
|
||||||
|
`org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager3` and
|
||||||
|
configure it in `bootstrap.xml` using the `security-manager` element, e.g.:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<broker xmlns="http://activemq.org/schema">
|
||||||
|
|
||||||
|
<security-manager class-name="com.foo.MySecurityManager">
|
||||||
|
<property key="myKey1" value="myValue1"/>
|
||||||
|
<property key="myKey2" value="myValue2"/>
|
||||||
|
</security-manager>
|
||||||
|
|
||||||
|
...
|
||||||
|
</broker>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `security-manager` example demonstrates how to do this is more detail.
|
||||||
|
|
|
@ -438,8 +438,12 @@ The bootstrap file is very simple. Let's take a look at an example:
|
||||||
`configuration` attribute. This is the main broker POJO necessary to do all
|
`configuration` attribute. This is the main broker POJO necessary to do all
|
||||||
the real messaging work.
|
the real messaging work.
|
||||||
|
|
||||||
- `jaas-security` - Configures security for the server. The `domain` attribute
|
- `jaas-security` - Configures JAAS-based security for the server. The
|
||||||
refers to the relevant login module entry in `login.config`.
|
`domain` attribute refers to the relevant login module entry in
|
||||||
|
`login.config`. If different behavior is needed then a custom security
|
||||||
|
manager can be configured by replacing `jaas-security` with
|
||||||
|
`security-manager`. See the "Custom Security Manager" section in the
|
||||||
|
[security chapter](security.md) for more details.
|
||||||
|
|
||||||
- `web` - Configures an embedded Jetty instance to serve web applications like
|
- `web` - Configures an embedded Jetty instance to serve web applications like
|
||||||
the admin console.
|
the admin console.
|
||||||
|
|
|
@ -91,6 +91,7 @@ under the License.
|
||||||
<module>scheduled-message</module>
|
<module>scheduled-message</module>
|
||||||
<module>security</module>
|
<module>security</module>
|
||||||
<module>security-ldap</module>
|
<module>security-ldap</module>
|
||||||
|
<module>security-manager</module>
|
||||||
<module>send-acknowledgements</module>
|
<module>send-acknowledgements</module>
|
||||||
<module>shared-consumer</module>
|
<module>shared-consumer</module>
|
||||||
<module>slow-consumer</module>
|
<module>slow-consumer</module>
|
||||||
|
@ -164,6 +165,7 @@ under the License.
|
||||||
<module>scheduled-message</module>
|
<module>scheduled-message</module>
|
||||||
<module>security</module>
|
<module>security</module>
|
||||||
<module>security-ldap</module>
|
<module>security-ldap</module>
|
||||||
|
<module>security-manager</module>
|
||||||
<module>send-acknowledgements</module>
|
<module>send-acknowledgements</module>
|
||||||
<module>shared-consumer</module>
|
<module>shared-consumer</module>
|
||||||
<module>slow-consumer</module>
|
<module>slow-consumer</module>
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
<?xml version='1.0'?>
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.activemq.examples.broker</groupId>
|
||||||
|
<artifactId>jms-examples</artifactId>
|
||||||
|
<version>2.11.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>security-manager</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>ActiveMQ Artemis JMS Security Manager Example</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<activemq.basedir>${project.basedir}/../../../..</activemq.basedir>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.activemq</groupId>
|
||||||
|
<artifactId>artemis-jms-client-all</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.activemq</groupId>
|
||||||
|
<artifactId>artemis-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.activemq</groupId>
|
||||||
|
<artifactId>artemis-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>create</id>
|
||||||
|
<goals>
|
||||||
|
<goal>create</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<libList>
|
||||||
|
<!-- For the security manager -->
|
||||||
|
<arg>org.apache.activemq.examples.broker:security-manager:${project.version}</arg>
|
||||||
|
</libList>
|
||||||
|
<ignore>${noServer}</ignore>
|
||||||
|
<allowAnonymous>false</allowAnonymous>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>start</id>
|
||||||
|
<goals>
|
||||||
|
<goal>cli</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<ignore>${noServer}</ignore>
|
||||||
|
<spawn>true</spawn>
|
||||||
|
<testURI>tcp://localhost:61616</testURI>
|
||||||
|
<testUser>bill</testUser>
|
||||||
|
<testPassword>activemq</testPassword>
|
||||||
|
<args>
|
||||||
|
<param>run</param>
|
||||||
|
</args>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>runClient</id>
|
||||||
|
<goals>
|
||||||
|
<goal>runClient</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<clientClass>org.apache.activemq.artemis.jms.example.SecurityManagerExample</clientClass>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>stop</id>
|
||||||
|
<goals>
|
||||||
|
<goal>cli</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<ignore>${noServer}</ignore>
|
||||||
|
<args>
|
||||||
|
<param>stop</param>
|
||||||
|
</args>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.activemq.examples.broker</groupId>
|
||||||
|
<artifactId>security-manager</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-clean-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>release</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.vladsch.flexmark</groupId>
|
||||||
|
<artifactId>markdown-page-generator-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
|
@ -0,0 +1,5 @@
|
||||||
|
# JMS Security Manager Example
|
||||||
|
|
||||||
|
To run the example, simply type **mvn verify** from this directory, or **mvn -PnoServer verify** if you want to start and create the broker manually.
|
||||||
|
|
||||||
|
This example is based on the "security" example and demonstrates how to implement a custom security manager. The custom security manager in this example simply logs details for authentication and authorization and then passes everything through to an instance of `org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager` (i.e. the default security manager).
|
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
* 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.jms.example;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.core.security.CheckType;
|
||||||
|
import org.apache.activemq.artemis.core.security.Role;
|
||||||
|
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||||
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
|
||||||
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
|
||||||
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager3;
|
||||||
|
|
||||||
|
public class JAASSecurityManagerWrapper implements ActiveMQSecurityManager3 {
|
||||||
|
ActiveMQJAASSecurityManager activeMQJAASSecurityManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String validateUser(String user, String password, RemotingConnection remotingConnection) {
|
||||||
|
System.out.println("validateUser(" + user + ", " + password + ", " + remotingConnection.getRemoteAddress() + ")");
|
||||||
|
return activeMQJAASSecurityManager.validateUser(user, password, remotingConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String validateUserAndRole(String user,
|
||||||
|
String password,
|
||||||
|
Set<Role> roles,
|
||||||
|
CheckType checkType,
|
||||||
|
String address,
|
||||||
|
RemotingConnection remotingConnection) {
|
||||||
|
System.out.println("validateUserAndRole(" + user + ", " + password + ", " + roles + ", " + checkType + ", " + address + ", " + remotingConnection.getRemoteAddress() + ")");
|
||||||
|
return activeMQJAASSecurityManager.validateUserAndRole(user, password, roles, checkType, address, remotingConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDomain() {
|
||||||
|
return activeMQJAASSecurityManager.getDomain();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validateUser(String user, String password) {
|
||||||
|
return activeMQJAASSecurityManager.validateUser(user, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validateUserAndRole(String user, String password, Set<Role> roles, CheckType checkType) {
|
||||||
|
return activeMQJAASSecurityManager.validateUserAndRole(user, password, roles, checkType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActiveMQSecurityManager init(Map<String, String> properties) {
|
||||||
|
activeMQJAASSecurityManager = new ActiveMQJAASSecurityManager(properties.get("domain"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,271 @@
|
||||||
|
/*
|
||||||
|
* 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.jms.example;
|
||||||
|
|
||||||
|
import javax.jms.Connection;
|
||||||
|
import javax.jms.ConnectionFactory;
|
||||||
|
import javax.jms.JMSException;
|
||||||
|
import javax.jms.JMSSecurityException;
|
||||||
|
import javax.jms.MessageConsumer;
|
||||||
|
import javax.jms.MessageProducer;
|
||||||
|
import javax.jms.Session;
|
||||||
|
import javax.jms.TextMessage;
|
||||||
|
import javax.jms.Topic;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
|
||||||
|
public class SecurityManagerExample {
|
||||||
|
|
||||||
|
public static void main(final String[] args) throws Exception {
|
||||||
|
boolean result = true;
|
||||||
|
Connection failConnection = null;
|
||||||
|
Connection billConnection = null;
|
||||||
|
Connection andrewConnection = null;
|
||||||
|
Connection frankConnection = null;
|
||||||
|
Connection samConnection = null;
|
||||||
|
|
||||||
|
InitialContext initialContext = null;
|
||||||
|
try {
|
||||||
|
// /Step 1. Create an initial context to perform the JNDI lookup.
|
||||||
|
initialContext = new InitialContext();
|
||||||
|
|
||||||
|
// Step 2. perform lookup on the topics
|
||||||
|
Topic genericTopic = (Topic) initialContext.lookup("topic/genericTopic");
|
||||||
|
Topic europeTopic = (Topic) initialContext.lookup("topic/europeTopic");
|
||||||
|
Topic usTopic = (Topic) initialContext.lookup("topic/usTopic");
|
||||||
|
|
||||||
|
// Step 3. perform a lookup on the Connection Factory
|
||||||
|
ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
|
||||||
|
|
||||||
|
// Step 4. Try to create a JMS Connection without user/password. It will fail.
|
||||||
|
try {
|
||||||
|
failConnection = cf.createConnection();
|
||||||
|
result = false;
|
||||||
|
} catch (JMSSecurityException e) {
|
||||||
|
System.out.println("Default user cannot get a connection. Details: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5. bill tries to make a connection using wrong password
|
||||||
|
try {
|
||||||
|
billConnection = createConnection("bill", "activemq1", cf);
|
||||||
|
result = false;
|
||||||
|
} catch (JMSException e) {
|
||||||
|
System.out.println("User bill failed to connect. Details: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 6. bill makes a good connection.
|
||||||
|
billConnection = createConnection("bill", "activemq", cf);
|
||||||
|
billConnection.start();
|
||||||
|
|
||||||
|
// Step 7. andrew makes a good connection.
|
||||||
|
andrewConnection = createConnection("andrew", "activemq1", cf);
|
||||||
|
andrewConnection.start();
|
||||||
|
|
||||||
|
// Step 8. frank makes a good connection.
|
||||||
|
frankConnection = createConnection("frank", "activemq2", cf);
|
||||||
|
frankConnection.start();
|
||||||
|
|
||||||
|
// Step 9. sam makes a good connection.
|
||||||
|
samConnection = createConnection("sam", "activemq3", cf);
|
||||||
|
samConnection.start();
|
||||||
|
|
||||||
|
// Step 10. Check every user can publish/subscribe genericTopics.
|
||||||
|
System.out.println("------------------------Checking permissions on " + genericTopic + "----------------");
|
||||||
|
checkUserSendAndReceive(genericTopic, billConnection, "bill");
|
||||||
|
checkUserSendAndReceive(genericTopic, andrewConnection, "andrew");
|
||||||
|
checkUserSendAndReceive(genericTopic, frankConnection, "frank");
|
||||||
|
checkUserSendAndReceive(genericTopic, samConnection, "sam");
|
||||||
|
System.out.println("-------------------------------------------------------------------------------------");
|
||||||
|
|
||||||
|
System.out.println("------------------------Checking permissions on " + europeTopic + "----------------");
|
||||||
|
|
||||||
|
// Step 11. Check permissions on news.europe.europeTopic for bill: can't send and can't receive
|
||||||
|
checkUserNoSendNoReceive(europeTopic, billConnection, "bill");
|
||||||
|
|
||||||
|
// Step 12. Check permissions on news.europe.europeTopic for andrew: can send but can't receive
|
||||||
|
checkUserSendNoReceive(europeTopic, andrewConnection, "andrew", frankConnection);
|
||||||
|
|
||||||
|
// Step 13. Check permissions on news.europe.europeTopic for frank: can't send but can receive
|
||||||
|
checkUserReceiveNoSend(europeTopic, frankConnection, "frank", andrewConnection);
|
||||||
|
|
||||||
|
// Step 14. Check permissions on news.europe.europeTopic for sam: can't send but can receive
|
||||||
|
checkUserReceiveNoSend(europeTopic, samConnection, "sam", andrewConnection);
|
||||||
|
System.out.println("-------------------------------------------------------------------------------------");
|
||||||
|
|
||||||
|
System.out.println("------------------------Checking permissions on " + usTopic + "----------------");
|
||||||
|
|
||||||
|
// Step 15. Check permissions on news.us.usTopic for bill: can't send and can't receive
|
||||||
|
checkUserNoSendNoReceive(usTopic, billConnection, "bill");
|
||||||
|
|
||||||
|
// Step 16. Check permissions on news.us.usTopic for andrew: can't send and can't receive
|
||||||
|
checkUserNoSendNoReceive(usTopic, andrewConnection, "andrew");
|
||||||
|
|
||||||
|
// Step 17. Check permissions on news.us.usTopic for frank: can both send and receive
|
||||||
|
checkUserSendAndReceive(usTopic, frankConnection, "frank");
|
||||||
|
|
||||||
|
// Step 18. Check permissions on news.us.usTopic for sam: can't send but can receive
|
||||||
|
checkUserReceiveNoSend(usTopic, samConnection, "sam", frankConnection);
|
||||||
|
System.out.println("-------------------------------------------------------------------------------------");
|
||||||
|
} finally {
|
||||||
|
// Step 19. Be sure to close our JMS resources!
|
||||||
|
if (failConnection != null) {
|
||||||
|
failConnection.close();
|
||||||
|
}
|
||||||
|
if (billConnection != null) {
|
||||||
|
billConnection.close();
|
||||||
|
}
|
||||||
|
if (andrewConnection != null) {
|
||||||
|
andrewConnection.close();
|
||||||
|
}
|
||||||
|
if (frankConnection != null) {
|
||||||
|
frankConnection.close();
|
||||||
|
}
|
||||||
|
if (samConnection != null) {
|
||||||
|
samConnection.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also the initialContext
|
||||||
|
if (initialContext != null) {
|
||||||
|
initialContext.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the user can receive message but cannot send message.
|
||||||
|
private static void checkUserReceiveNoSend(final Topic topic,
|
||||||
|
final Connection connection,
|
||||||
|
final String user,
|
||||||
|
final Connection sendingConn) throws JMSException {
|
||||||
|
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
|
MessageProducer producer = session.createProducer(topic);
|
||||||
|
MessageConsumer consumer = session.createConsumer(topic);
|
||||||
|
TextMessage msg = session.createTextMessage("hello-world-1");
|
||||||
|
|
||||||
|
try {
|
||||||
|
producer.send(msg);
|
||||||
|
throw new IllegalStateException("Security setting is broken! User " + user +
|
||||||
|
" can send message [" +
|
||||||
|
msg.getText() +
|
||||||
|
"] to topic " +
|
||||||
|
topic);
|
||||||
|
} catch (JMSException e) {
|
||||||
|
System.out.println("User " + user + " cannot send message [" + msg.getText() + "] to topic: " + topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now send a good message
|
||||||
|
Session session1 = sendingConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
|
producer = session1.createProducer(topic);
|
||||||
|
producer.send(msg);
|
||||||
|
|
||||||
|
TextMessage receivedMsg = (TextMessage) consumer.receive(2000);
|
||||||
|
|
||||||
|
if (receivedMsg != null) {
|
||||||
|
System.out.println("User " + user + " can receive message [" + receivedMsg.getText() + "] from topic " + topic);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Security setting is broken! User " + user + " cannot receive message from topic " + topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
session1.close();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the user can send message but cannot receive message
|
||||||
|
private static void checkUserSendNoReceive(final Topic topic,
|
||||||
|
final Connection connection,
|
||||||
|
final String user,
|
||||||
|
final Connection receivingConn) throws JMSException {
|
||||||
|
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
|
MessageProducer producer = session.createProducer(topic);
|
||||||
|
try {
|
||||||
|
session.createConsumer(topic);
|
||||||
|
} catch (JMSException e) {
|
||||||
|
System.out.println("User " + user + " cannot receive any message from topic " + topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session session1 = receivingConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
|
MessageConsumer goodConsumer = session1.createConsumer(topic);
|
||||||
|
|
||||||
|
TextMessage msg = session.createTextMessage("hello-world-2");
|
||||||
|
producer.send(msg);
|
||||||
|
|
||||||
|
TextMessage receivedMsg = (TextMessage) goodConsumer.receive(2000);
|
||||||
|
if (receivedMsg != null) {
|
||||||
|
System.out.println("User " + user + " can send message [" + receivedMsg.getText() + "] to topic " + topic);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Security setting is broken! User " + user +
|
||||||
|
" cannot send message [" +
|
||||||
|
msg.getText() +
|
||||||
|
"] to topic " +
|
||||||
|
topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
session.close();
|
||||||
|
session1.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the user has neither send nor receive permission on topic
|
||||||
|
private static void checkUserNoSendNoReceive(final Topic topic,
|
||||||
|
final Connection connection,
|
||||||
|
final String user) throws JMSException {
|
||||||
|
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
|
MessageProducer producer = session.createProducer(topic);
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createConsumer(topic);
|
||||||
|
} catch (JMSException e) {
|
||||||
|
System.out.println("User " + user + " cannot create consumer on topic " + topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextMessage msg = session.createTextMessage("hello-world-3");
|
||||||
|
try {
|
||||||
|
producer.send(msg);
|
||||||
|
throw new IllegalStateException("Security setting is broken! User " + user +
|
||||||
|
" can send message [" +
|
||||||
|
msg.getText() +
|
||||||
|
"] to topic " +
|
||||||
|
topic);
|
||||||
|
} catch (JMSException e) {
|
||||||
|
System.out.println("User " + user + " cannot send message [" + msg.getText() + "] to topic: " + topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the user connection has both send and receive permissions on the topic
|
||||||
|
private static void checkUserSendAndReceive(final Topic topic,
|
||||||
|
final Connection connection,
|
||||||
|
final String user) throws JMSException {
|
||||||
|
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
|
TextMessage msg = session.createTextMessage("hello-world-4");
|
||||||
|
MessageProducer producer = session.createProducer(topic);
|
||||||
|
MessageConsumer consumer = session.createConsumer(topic);
|
||||||
|
producer.send(msg);
|
||||||
|
TextMessage receivedMsg = (TextMessage) consumer.receive(5000);
|
||||||
|
if (receivedMsg != null) {
|
||||||
|
System.out.println("User " + user + " can send message: [" + msg.getText() + "] to topic: " + topic);
|
||||||
|
System.out.println("User " + user + " can receive message: [" + msg.getText() + "] from topic: " + topic);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Error! User " + user + " cannot receive the message! ");
|
||||||
|
}
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Connection createConnection(final String username,
|
||||||
|
final String password,
|
||||||
|
final ConnectionFactory cf) throws JMSException {
|
||||||
|
return cf.createConnection(username, password);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
## ---------------------------------------------------------------------------
|
||||||
|
## 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.
|
||||||
|
## ---------------------------------------------------------------------------
|
||||||
|
user=bill,andrew,frank,sam
|
||||||
|
europe-user=andrew
|
||||||
|
news-user=frank,sam
|
||||||
|
us-user=frank
|
|
@ -0,0 +1,20 @@
|
||||||
|
## ---------------------------------------------------------------------------
|
||||||
|
## 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.
|
||||||
|
## ---------------------------------------------------------------------------
|
||||||
|
bill = ENC(1024:020FEC8DB7EBBCB987FD25F1188EA71FA13FD4E0BF504963891EDC97E1ED1285:3E53D34A96F9995612C7C585CA04BA63CF5F531C92510E882960F848BFC3982AF47FCD40AB888F9AC10648CCEBA1DD52C0F0A312B2C90225D9A46DDC50198B3C)
|
||||||
|
andrew = ENC(1024:3E09F4D16A6970F3C40E24784AFE64AFD66349174AB20B2609109646A8F0561F:F22063143058EBCF47A0ACA1C29DBCB82C4AF15E510F5C801B47928AEA1836D1480BFD0DFD0320BA567D1A32C98859C02350AE271DC530F29D7E16E910E251AD)
|
||||||
|
frank = ENC(1024:49292EEC8AA19AB5390A0F0D67AA5A3978DE1AF0F561B641A1CE90B3C9637AAD:22A8F9A4B144B9CC173F3B1D5A2B09FE57642234534C2EB3A805DB7D5F7FEA398B58EB9380B8EA69B916B5CFA23BC7573E09A87A20C0DF1A35A1134270260BE4)
|
||||||
|
sam = ENC(1024:39832F10D9734D7E6EECE16BCEAA5E2917D384B4CE482A2A4B3D3E7A550B0A5C:CCA47914C6DD64AE6B69FE977BB445CBCDEA50D458E7F42AA341FA84A11C302E2EAB072E57B41A636589C89246911A6A49424CBA4B629F4846826183E9AD9DA1)
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<broker xmlns="http://activemq.org/schema">
|
||||||
|
|
||||||
|
<security-manager class-name="org.apache.activemq.artemis.jms.example.JAASSecurityManagerWrapper">
|
||||||
|
<property key="domain" value="activemq"/>
|
||||||
|
</security-manager>
|
||||||
|
|
||||||
|
<!-- artemis.URI.instance is parsed from artemis.instance by the CLI startup.
|
||||||
|
This is to avoid situations where you could have spaces or special characters on this URI -->
|
||||||
|
<server configuration="file:/home/jbertram/jboss/src/activemq-artemis/examples/features/standard/security-manager/target/server0/etc//broker.xml"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</broker>
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
|
||||||
|
<core xmlns="urn:activemq:core">
|
||||||
|
|
||||||
|
<bindings-directory>./data/messaging/bindings</bindings-directory>
|
||||||
|
|
||||||
|
<journal-directory>./data/messaging/journal</journal-directory>
|
||||||
|
|
||||||
|
<large-messages-directory>./data/messaging/largemessages</large-messages-directory>
|
||||||
|
|
||||||
|
<paging-directory>./data/messaging/paging</paging-directory>
|
||||||
|
|
||||||
|
<!-- Acceptors -->
|
||||||
|
<acceptors>
|
||||||
|
<acceptor name="netty-acceptor">tcp://localhost:61616</acceptor>
|
||||||
|
</acceptors>
|
||||||
|
|
||||||
|
<!-- Other config -->
|
||||||
|
|
||||||
|
<security-settings>
|
||||||
|
<!-- any user can have full control of generic topics -->
|
||||||
|
<security-setting match="#">
|
||||||
|
<permission roles="user" type="createDurableQueue"/>
|
||||||
|
<permission roles="user" type="deleteDurableQueue"/>
|
||||||
|
<permission roles="user" type="createNonDurableQueue"/>
|
||||||
|
<permission roles="user" type="deleteNonDurableQueue"/>
|
||||||
|
<permission roles="user" type="send"/>
|
||||||
|
<permission roles="user" type="consume"/>
|
||||||
|
</security-setting>
|
||||||
|
|
||||||
|
<security-setting match="news.europe.#">
|
||||||
|
<permission roles="user" type="createDurableQueue"/>
|
||||||
|
<permission roles="user" type="deleteDurableQueue"/>
|
||||||
|
<permission roles="user" type="createNonDurableQueue"/>
|
||||||
|
<permission roles="user" type="deleteNonDurableQueue"/>
|
||||||
|
<permission roles="europe-user" type="send"/>
|
||||||
|
<permission roles="news-user" type="consume"/>
|
||||||
|
</security-setting>
|
||||||
|
|
||||||
|
<security-setting match="news.us.#">
|
||||||
|
<permission roles="user" type="createDurableQueue"/>
|
||||||
|
<permission roles="user" type="deleteDurableQueue"/>
|
||||||
|
<permission roles="user" type="createNonDurableQueue"/>
|
||||||
|
<permission roles="user" type="deleteNonDurableQueue"/>
|
||||||
|
<permission roles="us-user" type="send"/>
|
||||||
|
<permission roles="news-user" type="consume"/>
|
||||||
|
</security-setting>
|
||||||
|
</security-settings>
|
||||||
|
|
||||||
|
<addresses>
|
||||||
|
<address name="genericTopic">
|
||||||
|
<multicast/>
|
||||||
|
</address>
|
||||||
|
<address name="news.europe.europeTopic">
|
||||||
|
<multicast/>
|
||||||
|
</address>
|
||||||
|
<address name="news.us.usTopic">
|
||||||
|
<multicast/>
|
||||||
|
</address>
|
||||||
|
</addresses>
|
||||||
|
</core>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,22 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory
|
||||||
|
connectionFactory.ConnectionFactory=tcp://localhost:61616
|
||||||
|
topic.topic/genericTopic=genericTopic
|
||||||
|
topic.topic/europeTopic=news.europe.europeTopic
|
||||||
|
topic.topic/usTopic=news.us.usTopic
|
Loading…
Reference in New Issue