ARTEMIS-4963 Check send auth on openwire producer create
Check that an attaching Openwire producer has SEND permission on the target destination and reject it if it does not instead of delaying checks until the actual send. For anonymous producers check early in the send process to reduce overhead in the JVM handling messages that are going to fail to send.
This commit is contained in:
parent
47acdc4517
commit
8250e611df
|
@ -1256,18 +1256,21 @@ public class OpenWireConnection extends AbstractRemotingConnection implements Se
|
|||
|
||||
// Avoid replaying dup commands
|
||||
if (!ss.getProducerIds().contains(info.getProducerId())) {
|
||||
ActiveMQDestination destination = info.getDestination();
|
||||
final ActiveMQDestination destination = info.getDestination();
|
||||
final AMQSession session = getSession(info.getProducerId().getParentId());
|
||||
|
||||
if (destination != null && !AdvisorySupport.isAdvisoryTopic(destination)) {
|
||||
OpenWireConnection.this.addDestination(new DestinationInfo(getContext().getConnectionId(), DestinationInfo.ADD_OPERATION_TYPE, destination));
|
||||
if (destination != null) {
|
||||
session.checkDestinationForSendPermission(destination);
|
||||
|
||||
if (!AdvisorySupport.isAdvisoryTopic(destination)) {
|
||||
OpenWireConnection.this.addDestination(new DestinationInfo(getContext().getConnectionId(), DestinationInfo.ADD_OPERATION_TYPE, destination));
|
||||
}
|
||||
}
|
||||
|
||||
ss.addProducer(info);
|
||||
getSession(info.getProducerId().getParentId()).getCoreSession().addProducer(
|
||||
info.getProducerId().toString(),
|
||||
OpenWireProtocolManagerFactory.OPENWIRE_PROTOCOL_NAME,
|
||||
info.getDestination() != null ? info.getDestination().getPhysicalName() : null);
|
||||
|
||||
session.getCoreSession().addProducer(info.getProducerId().toString(),
|
||||
OpenWireProtocolManagerFactory.OPENWIRE_PROTOCOL_NAME,
|
||||
info.getDestination() != null ? info.getDestination().getPhysicalName() : null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.activemq.artemis.core.protocol.openwire.OpenWireConnection;
|
|||
import org.apache.activemq.artemis.core.protocol.openwire.OpenWireMessageConverter;
|
||||
import org.apache.activemq.artemis.core.protocol.openwire.OpenWireProtocolManager;
|
||||
import org.apache.activemq.artemis.core.protocol.openwire.util.OpenWireUtil;
|
||||
import org.apache.activemq.artemis.core.security.CheckType;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.MessageReference;
|
||||
|
@ -364,6 +365,14 @@ public class AMQSession implements SessionCallback {
|
|||
|
||||
final ActiveMQDestination destination = messageSend.getDestination();
|
||||
|
||||
if (producerInfo.getDestination() == null) {
|
||||
// a named producer will have its target destination checked on create but an
|
||||
// anonymous producer can send to different addresses on each send so we need to
|
||||
// check here before going into message conversion and pre-dispatch stages before
|
||||
// the target gets a security check.
|
||||
checkDestinationForSendPermission(destination);
|
||||
}
|
||||
|
||||
final ActiveMQDestination[] actualDestinations;
|
||||
final int actualDestinationsCount;
|
||||
if (destination.isComposite()) {
|
||||
|
@ -568,4 +577,25 @@ public class AMQSession implements SessionCallback {
|
|||
public boolean isInternal() {
|
||||
return sessInfo.getSessionId().getValue() == -1;
|
||||
}
|
||||
|
||||
public void checkDestinationForSendPermission(ActiveMQDestination destination) throws Exception {
|
||||
if (server.getSecurityStore().isSecurityEnabled()) {
|
||||
if (destination.isComposite()) {
|
||||
for (ActiveMQDestination composite : destination.getCompositeDestinations()) {
|
||||
doCheckDestinationForSendPermission(composite);
|
||||
}
|
||||
} else {
|
||||
doCheckDestinationForSendPermission(destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doCheckDestinationForSendPermission(ActiveMQDestination destination) throws Exception {
|
||||
final SimpleString destinationName = SimpleString.of(destination.getPhysicalName());
|
||||
final SimpleString address = CompositeAddress.extractAddressName(destinationName);
|
||||
final SimpleString queue = CompositeAddress.isFullyQualified(destinationName) ?
|
||||
CompositeAddress.extractQueueName(destinationName) : null;
|
||||
|
||||
server.getSecurityStore().check(address, queue, CheckType.SEND, getCoreSession());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ import javax.jms.Topic;
|
|||
import javax.jms.TopicSubscriber;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.QueueConfiguration;
|
||||
import org.apache.activemq.artemis.api.core.RoutingType;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -148,10 +150,18 @@ public class BasicSecurityTest extends BasicOpenWireTest {
|
|||
|
||||
MessageProducer producer = null;
|
||||
|
||||
producer = receivingSession.createProducer(dest);
|
||||
try {
|
||||
receivingSession.createProducer(dest);
|
||||
fail("Should not be able to create a producer when not authorized to send");
|
||||
} catch (JMSSecurityException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
producer = receivingSession.createProducer(null);
|
||||
|
||||
try {
|
||||
producer.send(message);
|
||||
producer.send(dest, message);
|
||||
fail("exception expected");
|
||||
} catch (JMSSecurityException e) {
|
||||
//expected
|
||||
producer.close();
|
||||
|
@ -185,6 +195,84 @@ public class BasicSecurityTest extends BasicOpenWireTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendReceiveAuthorizationOnComposite() throws Exception {
|
||||
Connection sendingConn = null;
|
||||
Connection receivingConn = null;
|
||||
|
||||
final String compositeName = queueName + "," + queueName2;
|
||||
|
||||
//Sender
|
||||
try {
|
||||
Destination composite = new ActiveMQQueue(compositeName);
|
||||
Destination dest1 = new ActiveMQQueue(queueName);
|
||||
Destination dest2 = new ActiveMQQueue(queueName2);
|
||||
|
||||
// Server must have this composite version of the Address and Queue for this test to work
|
||||
// as the user does not have auto create permissions and it will try to create this.
|
||||
server.createQueue(QueueConfiguration.of(compositeName).setAddress(compositeName).setRoutingType(RoutingType.ANYCAST));
|
||||
|
||||
receivingConn = factory.createConnection("openwireReceiver", "ReCeIvEr");
|
||||
receivingConn.start();
|
||||
|
||||
sendingConn = factory.createConnection("openwireSender", "SeNdEr");
|
||||
sendingConn.start();
|
||||
|
||||
Session sendingSession = sendingConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Session receivingSession = receivingConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
TextMessage message = sendingSession.createTextMessage("Hello World");
|
||||
|
||||
MessageProducer producer = null;
|
||||
|
||||
try {
|
||||
receivingSession.createProducer(composite);
|
||||
fail("Should get a security exception on create");
|
||||
} catch (JMSSecurityException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
producer = receivingSession.createProducer(null);
|
||||
|
||||
try {
|
||||
producer.send(composite, message);
|
||||
fail("exception expected");
|
||||
} catch (JMSSecurityException e) {
|
||||
//expected
|
||||
producer.close();
|
||||
}
|
||||
|
||||
producer = sendingSession.createProducer(composite);
|
||||
producer.send(message);
|
||||
|
||||
try {
|
||||
sendingSession.createConsumer(dest1);
|
||||
fail("exception expected");
|
||||
} catch (JMSSecurityException e) {
|
||||
e.printStackTrace();
|
||||
//expected
|
||||
}
|
||||
|
||||
MessageConsumer consumer1 = receivingSession.createConsumer(dest1);
|
||||
TextMessage received1 = (TextMessage) consumer1.receive(5000);
|
||||
MessageConsumer consumer2 = receivingSession.createConsumer(dest2);
|
||||
TextMessage received2 = (TextMessage) consumer2.receive(5000);
|
||||
|
||||
assertNotNull(received1);
|
||||
assertEquals("Hello World", received1.getText());
|
||||
assertNotNull(received2);
|
||||
assertEquals("Hello World", received2.getText());
|
||||
} finally {
|
||||
if (sendingConn != null) {
|
||||
sendingConn.close();
|
||||
}
|
||||
|
||||
if (receivingConn != null) {
|
||||
receivingConn.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTempDestinationAuthorization() throws Exception {
|
||||
Connection conn1 = null;
|
||||
|
@ -444,5 +532,4 @@ public class BasicSecurityTest extends BasicOpenWireTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,70 +16,675 @@
|
|||
*/
|
||||
package org.apache.activemq.artemis.tests.integration.openwire;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
import java.util.HashSet;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSSecurityException;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import org.apache.activemq.artemis.api.core.QueueConfiguration;
|
||||
import org.apache.activemq.artemis.api.core.RoutingType;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.security.Role;
|
||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
|
||||
import org.apache.activemq.artemis.tests.util.RandomUtil;
|
||||
import org.apache.activemq.artemis.utils.CompositeAddress;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.Timeout;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
@Timeout(20)
|
||||
public class SecurityOpenWireTest extends BasicOpenWireTest {
|
||||
|
||||
// This set specifically tests that two FQQNs under the same address can be isolated for
|
||||
// two distinct users each being allowed only access to a given queue under the address
|
||||
private final String FQQN_USER1 = "fqqnUser1";
|
||||
private final String FQQN_USER2 = "fqqnUser2";
|
||||
private final String FQQN_ROLE1 = "fqqnRole1";
|
||||
private final String FQQN_ROLE2 = "fqqnRole2";
|
||||
private final String FQQN_ADDRESS = "fqqnAddress";
|
||||
private final String FQQN_QUEUE1 = "fqqnQueue1";
|
||||
private final String FQQN_QUEUE2 = "fqqnQueue2";
|
||||
private final String FQQN_FOR_USER1 = CompositeAddress.toFullyQualified(FQQN_ADDRESS, FQQN_QUEUE1);
|
||||
private final String FQQN_FOR_USER2 = CompositeAddress.toFullyQualified(FQQN_ADDRESS, FQQN_QUEUE2);
|
||||
|
||||
private final String ALLOWED_USER = "allowedUser";
|
||||
private final String ALLOWED_ROLE = "allowedRole";
|
||||
private final String ALLOWED_USER_ALTERNATE = "allowedUserAlternate";
|
||||
private final String ALLOWED_ROLE_ALTERNATE = "allowedRoleAlternate";
|
||||
private final String DENIED_USER = "deniedUser";
|
||||
private final String DENIED_ROLE = "deniedRole";
|
||||
private final String PASS = RandomUtil.randomString();
|
||||
private final String ADDRESS = "myAddress";
|
||||
private final String ALTERNATE_ADDRESS = "myOtherAddress";
|
||||
private final String ALTERNATE_QUEUE = "myOtherQueue";
|
||||
private final String QUEUE = "myQueue";
|
||||
private final String FQQN = CompositeAddress.toFullyQualified(ADDRESS, QUEUE);
|
||||
private final String FQQN_ALTERNATE = CompositeAddress.toFullyQualified(ALTERNATE_ADDRESS, ALTERNATE_QUEUE);
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
//this system property is used to construct the executor in
|
||||
//org.apache.activemq.transport.AbstractInactivityMonitor.createExecutor()
|
||||
//and affects the pool's shutdown time. (default is 30 sec)
|
||||
//set it to 2 to make tests shutdown quicker.
|
||||
// this system property is used to construct the executor in
|
||||
// org.apache.activemq.transport.AbstractInactivityMonitor.createExecutor()
|
||||
// and affects the pool's shutdown time. (default is 30 sec)
|
||||
// set it to 2 to make tests shutdown quicker.
|
||||
System.setProperty("org.apache.activemq.transport.AbstractInactivityMonitor.keepAliveTime", "2");
|
||||
this.realStore = true;
|
||||
|
||||
realStore = true;
|
||||
enableSecurity = true;
|
||||
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void extraServerConfig(Configuration serverConfig) {
|
||||
protected void extraServerConfig(Configuration configuration) {
|
||||
super.extraServerConfig(configuration);
|
||||
|
||||
super.extraServerConfig(serverConfig);
|
||||
ActiveMQJAASSecurityManager securityManager = (ActiveMQJAASSecurityManager) server.getSecurityManager();
|
||||
securityManager.getConfiguration().addUser("denyQ", "denyQ");
|
||||
securityManager.getConfiguration().addRole("denyQ", "denyQ");
|
||||
securityManager.getConfiguration().addRole("denyQ", "advisoryReceiver");
|
||||
final Role allowed = new Role(ALLOWED_ROLE, true, false, false, false, false, false, false, false, true, false, false, false);
|
||||
final Role denied = new Role(DENIED_ROLE, false, false, false, false, false, false, false, false, false, false, false, false);
|
||||
final Role alternate = new Role(ALLOWED_ROLE_ALTERNATE, true, false, false, false, false, false, false, false, true, false, false, false);
|
||||
|
||||
final ActiveMQJAASSecurityManager securityManager = (ActiveMQJAASSecurityManager) server.getSecurityManager();
|
||||
|
||||
securityManager.getConfiguration().addUser(ALLOWED_USER, PASS);
|
||||
securityManager.getConfiguration().addRole(ALLOWED_USER, ALLOWED_ROLE);
|
||||
securityManager.getConfiguration().addUser(ALLOWED_USER_ALTERNATE, PASS);
|
||||
securityManager.getConfiguration().addRole(ALLOWED_USER_ALTERNATE, ALLOWED_ROLE_ALTERNATE);
|
||||
securityManager.getConfiguration().addUser(DENIED_USER, PASS);
|
||||
securityManager.getConfiguration().addRole(DENIED_USER, DENIED_ROLE);
|
||||
securityManager.getConfiguration().addRole(ALLOWED_USER, "advisoryReceiver");
|
||||
securityManager.getConfiguration().addRole(ALLOWED_USER_ALTERNATE, "advisoryReceiver");
|
||||
securityManager.getConfiguration().addRole(DENIED_USER, "advisoryReceiver");
|
||||
|
||||
configuration.putSecurityRoles(FQQN, Set.of(allowed, denied));
|
||||
configuration.putSecurityRoles(ADDRESS, Set.of(allowed, denied));
|
||||
configuration.putSecurityRoles(FQQN_ALTERNATE, Set.of(alternate, denied));
|
||||
configuration.putSecurityRoles(ALTERNATE_ADDRESS, Set.of(alternate, denied));
|
||||
|
||||
configuration.addQueueConfiguration(QueueConfiguration.of(QUEUE).setAddress(ADDRESS).setRoutingType(RoutingType.ANYCAST));
|
||||
configuration.addQueueConfiguration(QueueConfiguration.of(ALTERNATE_QUEUE).setAddress(ALTERNATE_ADDRESS).setRoutingType(RoutingType.ANYCAST));
|
||||
|
||||
// This section create a split FQQN set under a single address where each user can only write to their
|
||||
// own Queue under the base FQQN address, these roles disallow auto create to ensure neither can just
|
||||
// create their way into a working configuration.
|
||||
|
||||
final Role fqqn1 = new Role(FQQN_ROLE1, true, false, false, false, false, false, false, false, false, false, false, false);
|
||||
final Role fqqn2 = new Role(FQQN_ROLE2, true, false, false, false, false, false, false, false, false, false, false, false);
|
||||
|
||||
securityManager.getConfiguration().addUser(FQQN_USER1, PASS);
|
||||
securityManager.getConfiguration().addRole(FQQN_USER1, FQQN_ROLE1);
|
||||
securityManager.getConfiguration().addRole(FQQN_USER1, "advisoryReceiver");
|
||||
securityManager.getConfiguration().addUser(FQQN_USER2, PASS);
|
||||
securityManager.getConfiguration().addRole(FQQN_USER2, FQQN_ROLE2);
|
||||
securityManager.getConfiguration().addRole(FQQN_USER2, "advisoryReceiver");
|
||||
|
||||
configuration.putSecurityRoles(FQQN_FOR_USER1, Set.of(fqqn1));
|
||||
configuration.putSecurityRoles(FQQN_FOR_USER2, Set.of(fqqn2));
|
||||
|
||||
configuration.addQueueConfiguration(QueueConfiguration.of(FQQN_FOR_USER1).setAddress(FQQN_ADDRESS).setRoutingType(RoutingType.ANYCAST));
|
||||
configuration.addQueueConfiguration(QueueConfiguration.of(FQQN_FOR_USER2).setAddress(FQQN_ADDRESS).setRoutingType(RoutingType.ANYCAST));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendNoAuth() throws Exception {
|
||||
Set<Role> roles = new HashSet<>();
|
||||
roles.add(new Role("programmers", false, false, false, false, false, false, false, false, false, false, false, false));
|
||||
public void testAnonymousSendNoAuthToQueue() throws Exception {
|
||||
doTestAnonymousSendNoAuth(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSendNoAuthToTopic() throws Exception {
|
||||
doTestAnonymousSendNoAuth(true);
|
||||
}
|
||||
|
||||
private void doTestAnonymousSendNoAuth(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(DENIED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Destination destination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(ADDRESS);
|
||||
} else {
|
||||
destination = session.createQueue(ADDRESS);
|
||||
}
|
||||
|
||||
final MessageProducer producer = session.createProducer(null);
|
||||
|
||||
server.getSecurityRepository().addMatch("denyQ", roles);
|
||||
String denyQ = "denyQ";
|
||||
server.createQueue(QueueConfiguration.of(denyQ).setRoutingType(RoutingType.ANYCAST));
|
||||
try (Connection connection = factory.createConnection(denyQ, denyQ)) {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(denyQ);
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
|
||||
try {
|
||||
producer.send(session.createTextMessage());
|
||||
fail();
|
||||
} catch (JMSException e) {
|
||||
//pass
|
||||
producer.send(destination, session.createTextMessage());
|
||||
fail("Should not be able to send to this destination");
|
||||
} catch (JMSSecurityException e) {
|
||||
// expected to fail as not authorized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSendWithAuthToQueue() throws Exception {
|
||||
doTestAnonymousSendWithAuth(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSendWithAuthToTopic() throws Exception {
|
||||
doTestAnonymousSendWithAuth(true);
|
||||
}
|
||||
|
||||
private void doTestAnonymousSendWithAuth(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(ALLOWED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final MessageProducer producer = session.createProducer(null);
|
||||
final Destination destination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(ADDRESS);
|
||||
} else {
|
||||
destination = session.createQueue(ADDRESS);
|
||||
}
|
||||
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
|
||||
try {
|
||||
producer.send(destination, session.createMessage());
|
||||
// Expected: can send to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("unexpected error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendWithAuthToQueue() throws Exception {
|
||||
doTestSendWithAuth(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendWithAuthToTopic() throws Exception {
|
||||
doTestSendWithAuth(true);
|
||||
}
|
||||
|
||||
private void doTestSendWithAuth(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(ALLOWED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Destination destination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(ADDRESS);
|
||||
} else {
|
||||
destination = session.createQueue(ADDRESS);
|
||||
}
|
||||
|
||||
final MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
|
||||
try {
|
||||
producer.send(session.createMessage());
|
||||
// Expected: can send to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("unexpected error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSenderNoAuthToQueue() throws Exception {
|
||||
doTestCreateSenderNoAuth(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSenderNoAuthToTopic() throws Exception {
|
||||
doTestCreateSenderNoAuth(true);
|
||||
}
|
||||
|
||||
private void doTestCreateSenderNoAuth(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(DENIED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Destination destination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(ADDRESS);
|
||||
} else {
|
||||
destination = session.createQueue(ADDRESS);
|
||||
}
|
||||
|
||||
try {
|
||||
session.createProducer(destination);
|
||||
fail("Should not be able to create producer on restricted destination");
|
||||
} catch (JMSSecurityException e) {
|
||||
// expected to fail as not authorized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSenderWithAuthToFQQNAsQueue() throws Exception {
|
||||
doTestCreateSenderWithAuthToFQQN(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSenderWithAuthToFQQNAsTopic() throws Exception {
|
||||
doTestCreateSenderWithAuthToFQQN(true);
|
||||
}
|
||||
|
||||
private void doTestCreateSenderWithAuthToFQQN(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(ALLOWED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Destination destination;
|
||||
final Destination otherDestination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(FQQN);
|
||||
otherDestination = session.createTopic(FQQN_ALTERNATE); // Does not have authorization to this FQQN
|
||||
} else {
|
||||
destination = session.createQueue(FQQN);
|
||||
otherDestination = session.createQueue(FQQN_ALTERNATE); // Does not have authorization to this FQQN
|
||||
}
|
||||
|
||||
try {
|
||||
session.createProducer(destination);
|
||||
// Expected: can attach to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to send to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
session.createProducer(otherDestination);
|
||||
fail("Should not be able to send to given alternate FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: cannot attach to FQQN destination that is not in the security match settings
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSenderNoAuthToFQQNAsQueue() throws Exception {
|
||||
doTestCreateSenderNoAuthToFQQN(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSenderNoAuthToFQQNAsTopic() throws Exception {
|
||||
doTestCreateSenderNoAuthToFQQN(true);
|
||||
}
|
||||
|
||||
private void doTestCreateSenderNoAuthToFQQN(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(DENIED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Destination destination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(FQQN);
|
||||
} else {
|
||||
destination = session.createQueue(FQQN);
|
||||
}
|
||||
|
||||
try {
|
||||
session.createProducer(destination);
|
||||
fail("Should not be able to send to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: cannot attach to denied destination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSenderWithAuthToFQQNAsQueue() throws Exception {
|
||||
doTestAnonymousSenderWithAuthToFQQN(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSenderWithAuthToFQQNAsTopic() throws Exception {
|
||||
doTestAnonymousSenderWithAuthToFQQN(true);
|
||||
}
|
||||
|
||||
private void doTestAnonymousSenderWithAuthToFQQN(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(ALLOWED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Destination destination;
|
||||
final Destination otherDestination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(FQQN);
|
||||
otherDestination = session.createTopic(FQQN_ALTERNATE); // Does not have authorization to this FQQN
|
||||
} else {
|
||||
destination = session.createQueue(FQQN);
|
||||
otherDestination = session.createQueue(FQQN_ALTERNATE); // Does not have authorization to this FQQN
|
||||
}
|
||||
|
||||
final MessageProducer producer = session.createProducer(null);
|
||||
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
|
||||
try {
|
||||
producer.send(destination, session.createMessage());
|
||||
// Expected: should send to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to send to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
producer.send(otherDestination, session.createMessage());
|
||||
fail("Should not be able to send to given alternate FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: should fail to send to this destination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSenderNoAuthToFQQNAsQueue() throws Exception {
|
||||
doTestAnonymousSenderNoAuthToFQQN(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSenderNoAuthToFQQNAsTopic() throws Exception {
|
||||
doTestAnonymousSenderNoAuthToFQQN(true);
|
||||
}
|
||||
|
||||
private void doTestAnonymousSenderNoAuthToFQQN(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(DENIED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Destination destination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(FQQN);
|
||||
} else {
|
||||
destination = session.createQueue(FQQN);
|
||||
}
|
||||
|
||||
final MessageProducer producer = session.createProducer(null);
|
||||
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
|
||||
try {
|
||||
producer.send(destination, session.createMessage());
|
||||
fail("Should not be able to send to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: cannot attach to denied destination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSendersWithFineGrainedAuthToFQQNAsQueues() throws Exception {
|
||||
doTestCreateSenderWithFineGrainedAuthToFQQNs(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSendersWithFineGrainedAuthToFQQNAsTopics() throws Exception {
|
||||
doTestCreateSenderWithFineGrainedAuthToFQQNs(true);
|
||||
}
|
||||
|
||||
private void doTestCreateSenderWithFineGrainedAuthToFQQNs(boolean topic) throws Exception {
|
||||
try (Connection connection1 = factory.createConnection(ALLOWED_USER, PASS);
|
||||
Connection connection2 = factory.createConnection(ALLOWED_USER_ALTERNATE, PASS)) {
|
||||
|
||||
final Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
final Destination destination1;
|
||||
final Destination destination2;
|
||||
|
||||
if (topic) {
|
||||
destination1 = session1.createTopic(FQQN);
|
||||
destination2 = session2.createTopic(FQQN_ALTERNATE);
|
||||
} else {
|
||||
destination1 = session1.createQueue(FQQN);
|
||||
destination2 = session2.createQueue(FQQN_ALTERNATE);
|
||||
}
|
||||
|
||||
try {
|
||||
session1.createProducer(destination1);
|
||||
// Expected: should be able to create sender to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to create sender to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
session1.createProducer(destination2);
|
||||
fail("Should not be able to create sender to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: should fail to create sender to this FQQN destination
|
||||
}
|
||||
|
||||
try {
|
||||
session2.createProducer(destination2);
|
||||
// Expected: should be able to create sender to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to create sender to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
session2.createProducer(destination1);
|
||||
fail("Should not be able to create sender to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: should fail to create sender to this FQQN destination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSendersWithFineGrainedAuthToFQQNAsQueues() throws Exception {
|
||||
doTestAnonymousSenderWithFineGrainedAuthToFQQNs(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSendersWithFineGrainedAuthToFQQNAsTopics() throws Exception {
|
||||
doTestAnonymousSenderWithFineGrainedAuthToFQQNs(true);
|
||||
}
|
||||
|
||||
private void doTestAnonymousSenderWithFineGrainedAuthToFQQNs(boolean topic) throws Exception {
|
||||
try (Connection connection1 = factory.createConnection(ALLOWED_USER, PASS);
|
||||
Connection connection2 = factory.createConnection(ALLOWED_USER_ALTERNATE, PASS)) {
|
||||
|
||||
final Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
final Destination destination1;
|
||||
final Destination destination2;
|
||||
|
||||
if (topic) {
|
||||
destination1 = session1.createTopic(FQQN);
|
||||
destination2 = session2.createTopic(FQQN_ALTERNATE);
|
||||
} else {
|
||||
destination1 = session1.createQueue(FQQN);
|
||||
destination2 = session2.createQueue(FQQN_ALTERNATE);
|
||||
}
|
||||
|
||||
final MessageProducer producer1 = session1.createProducer(null);
|
||||
final MessageProducer producer2 = session2.createProducer(null);
|
||||
|
||||
producer1.setDeliveryMode(DeliveryMode.PERSISTENT); // ALLOWED USER
|
||||
producer2.setDeliveryMode(DeliveryMode.PERSISTENT); // ALTERNATE ALLOWED USER
|
||||
|
||||
try {
|
||||
producer1.send(destination1, session1.createMessage());
|
||||
// Expected: should send to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to send to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
producer1.send(destination2, session1.createMessage());
|
||||
fail("Should not be able to send to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: should fail to send to this destination
|
||||
}
|
||||
|
||||
try {
|
||||
producer2.send(destination2, session2.createMessage());
|
||||
// Expected: should send to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to send to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
producer2.send(destination1, session2.createMessage());
|
||||
fail("Should not be able to send to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: should fail to send to this destination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSenderNoAuthToCompositeAsQueue() throws Exception {
|
||||
doTestCreateSenderNoAuthToComposite(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSenderNoAuthToCompositeAsTopic() throws Exception {
|
||||
doTestCreateSenderNoAuthToComposite(true);
|
||||
}
|
||||
|
||||
private void doTestCreateSenderNoAuthToComposite(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(DENIED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Destination destination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(ADDRESS + "," + ALTERNATE_ADDRESS);
|
||||
} else {
|
||||
destination = session.createQueue(ADDRESS + "," + ALTERNATE_ADDRESS);
|
||||
}
|
||||
|
||||
try {
|
||||
session.createProducer(destination);
|
||||
fail("Should not be able to create a producer to given composite destination");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: cannot attach to denied destination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSenderNoAuthToCompositeAsQueue() throws Exception {
|
||||
doTestAnonymousSenderNoAuthToComposite(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousSenderNoAuthToCompositeAsTopic() throws Exception {
|
||||
doTestAnonymousSenderNoAuthToComposite(true);
|
||||
}
|
||||
|
||||
private void doTestAnonymousSenderNoAuthToComposite(boolean topic) throws Exception {
|
||||
try (Connection connection = factory.createConnection(DENIED_USER, PASS)) {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Destination destination;
|
||||
|
||||
if (topic) {
|
||||
destination = session.createTopic(ADDRESS + "," + ALTERNATE_ADDRESS);
|
||||
} else {
|
||||
destination = session.createQueue(ADDRESS + "," + ALTERNATE_ADDRESS);
|
||||
}
|
||||
|
||||
final MessageProducer producer = session.createProducer(null);
|
||||
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
|
||||
try {
|
||||
producer.send(destination, session.createMessage());
|
||||
fail("Should not be able to send to given composite destination");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: cannot attach to denied destination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFQQNUserIsolationUnderSameAddressOnSenderCreate() throws Exception {
|
||||
try (Connection connection1 = factory.createConnection(FQQN_USER1, PASS);
|
||||
Connection connection2 = factory.createConnection(FQQN_USER2, PASS)) {
|
||||
|
||||
final Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
final Destination destination1 = session1.createQueue(FQQN_FOR_USER1);
|
||||
final Destination destination2 = session2.createQueue(FQQN_FOR_USER2);
|
||||
|
||||
// FQQN USER 1 is isolated to the queue under address created for it
|
||||
|
||||
try {
|
||||
session1.createProducer(destination1);
|
||||
// Expected: should be able to create sender to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to create sender to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
session1.createProducer(destination2);
|
||||
fail("Should not be able to create sender to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: should fail to create sender to this FQQN destination
|
||||
}
|
||||
|
||||
// FQQN USER 2 is isolated to the queue under address created for it
|
||||
|
||||
try {
|
||||
session2.createProducer(destination2);
|
||||
// Expected: should be able to create sender to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to create sender to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
session2.createProducer(destination1);
|
||||
fail("Should not be able to create sender to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: should fail to create sender to this FQQN destination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFQQNUserIsolationUnderSameAddressWithAnonymousSends() throws Exception {
|
||||
try (Connection connection1 = factory.createConnection(FQQN_USER1, PASS);
|
||||
Connection connection2 = factory.createConnection(FQQN_USER2, PASS)) {
|
||||
|
||||
final Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
final Destination destination1 = session1.createQueue(FQQN_FOR_USER1);
|
||||
final Destination destination2 = session2.createQueue(FQQN_FOR_USER2);
|
||||
|
||||
final MessageProducer producer1 = session1.createProducer(null);
|
||||
final MessageProducer producer2 = session2.createProducer(null);
|
||||
|
||||
// FQQN USER 1 is isolated to the queue under address created for it
|
||||
|
||||
try {
|
||||
producer1.send(destination1, session1.createMessage());
|
||||
// Expected: should be able to send to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to send to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
producer1.send(destination2, session1.createMessage());
|
||||
fail("Should not be able to send to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: should fail to send to this FQQN destination
|
||||
}
|
||||
|
||||
// FQQN USER 2 is isolated to the queue under address created for it
|
||||
|
||||
try {
|
||||
producer2.send(destination2, session1.createMessage());
|
||||
// Expected: should be able to send to allowed destination
|
||||
} catch (JMSSecurityException e) {
|
||||
fail("Should be able to send to given FQQN: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
producer2.send(destination1, session1.createMessage());
|
||||
fail("Should not be able to send to given FQQN");
|
||||
} catch (JMSSecurityException e) {
|
||||
// Expected: should fail to send to this FQQN destination
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue