[ 
https://issues.apache.org/jira/browse/ARTEMIS-4969?focusedWorklogId=928599&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-928599
 ]

ASF GitHub Bot logged work on ARTEMIS-4969:
-------------------------------------------

                Author: ASF GitHub Bot
            Created on: 02/Aug/24 23:54
            Start Date: 02/Aug/24 23:54
    Worklog Time Spent: 10m 
      Work Description: gemmellr commented on code in PR #5125:
URL: https://github.com/apache/activemq-artemis/pull/5125#discussion_r1702404262


##########
tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpTargetedFQQNSecurityTest.java:
##########
@@ -0,0 +1,362 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.tests.integration.amqp;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.jms.JMSSecurityException;
+
+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.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.core.server.Queue;
+import 
org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.activemq.artemis.tests.util.Wait;
+import org.apache.activemq.artemis.utils.CompositeAddress;
+import org.apache.activemq.transport.amqp.client.AmqpClient;
+import org.apache.activemq.transport.amqp.client.AmqpConnection;
+import org.apache.activemq.transport.amqp.client.AmqpMessage;
+import org.apache.activemq.transport.amqp.client.AmqpReceiver;
+import org.apache.activemq.transport.amqp.client.AmqpSender;
+import org.apache.activemq.transport.amqp.client.AmqpSession;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+
+/**
+ * Test that AMQP senders and receivers can send to and receive from FQQN 
addresses when
+ * the broker security policy is configured to limit access to those resources.
+ */
+@Timeout(20)
+public class AmqpTargetedFQQNSecurityTest extends AmqpClientTestSupport {
+
+   private final String FQQN_SENDER_1 = "fqqnSender1";
+   private final String FQQN_SENDER_2 = "fqqnSender2";
+   private final String FQQN_RECEIVER_1 = "fqqnReceiver1";
+   private final String FQQN_RECEIVER_2 = "fqqnReceiver2";
+   private final String FQQN_SENDER1_ROLE = "fqqnSender1Role";
+   private final String FQQN_SENDER2_ROLE = "fqqnSender2Role";
+   private final String FQQN_RECEIVER1_ROLE = "fqqnReceiver1Role";
+   private final String FQQN_RECEIVER2_ROLE = "fqqnReceiver2Role";
+   private final String FQQN_ADDRESS = "fqqnAddress";
+   private final String FQQN_QUEUE1 = "fqqnQueue1";
+   private final String FQQN_QUEUE2 = "fqqnQueue2";
+   private final String FQQN_1 = 
CompositeAddress.toFullyQualified(FQQN_ADDRESS, FQQN_QUEUE1);
+   private final String FQQN_2 = 
CompositeAddress.toFullyQualified(FQQN_ADDRESS, FQQN_QUEUE2);
+   private final String PASS = UUID.randomUUID().toString();
+
+   @Override
+   protected boolean isSecurityEnabled() {
+      return true;
+   }
+
+   @Override
+   protected void enableSecurity(ActiveMQServer server, String... 
securityMatches) {
+      ActiveMQJAASSecurityManager securityManager = 
(ActiveMQJAASSecurityManager) server.getSecurityManager();
+      Configuration configuration = server.getConfiguration();
+
+      // This section create a split FQQN set under a single address where 
each user can only read or 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 fqqnSender1Role = new Role(FQQN_SENDER1_ROLE, true, false, 
false, false, false, false, false, false, false, false, false, false);
+      final Role fqqnSender2Role = new Role(FQQN_SENDER2_ROLE, true, false, 
false, false, false, false, false, false, false, false, false, false);
+      final Role fqqnReceiver1Role = new Role(FQQN_RECEIVER1_ROLE, false, 
true, false, false, false, false, false, false, false, false, true, false);
+      final Role fqqnReceiver2Role = new Role(FQQN_RECEIVER2_ROLE, false, 
true, false, false, false, false, false, false, false, false, true, false);
+
+      // Senders
+      securityManager.getConfiguration().addUser(FQQN_SENDER_1, PASS);
+      securityManager.getConfiguration().addRole(FQQN_SENDER_1, 
FQQN_SENDER1_ROLE);
+      securityManager.getConfiguration().addUser(FQQN_SENDER_2, PASS);
+      securityManager.getConfiguration().addRole(FQQN_SENDER_2, 
FQQN_SENDER2_ROLE);
+
+      // Receivers
+      securityManager.getConfiguration().addUser(FQQN_RECEIVER_1, PASS);
+      securityManager.getConfiguration().addRole(FQQN_RECEIVER_1, 
FQQN_RECEIVER1_ROLE);
+      securityManager.getConfiguration().addUser(FQQN_RECEIVER_2, PASS);
+      securityManager.getConfiguration().addRole(FQQN_RECEIVER_2, 
FQQN_RECEIVER2_ROLE);
+
+      configuration.putSecurityRoles(FQQN_1, Set.of(fqqnSender1Role, 
fqqnReceiver1Role));
+      configuration.putSecurityRoles(FQQN_2, Set.of(fqqnSender2Role, 
fqqnReceiver2Role));
+
+      
configuration.addQueueConfiguration(QueueConfiguration.of(FQQN_1).setAddress(FQQN_ADDRESS).setRoutingType(RoutingType.ANYCAST));
+      
configuration.addQueueConfiguration(QueueConfiguration.of(FQQN_2).setAddress(FQQN_ADDRESS).setRoutingType(RoutingType.ANYCAST));
+
+      server.getConfiguration().setSecurityEnabled(true);
+   }
+
+   @Test
+   public void testSender1CanWriteToAssignedFQQN() throws Exception {
+      doTestSenderCanWriteToAssignedFQQN(FQQN_SENDER_1, FQQN_1);
+   }
+
+   @Test
+   public void testSender2CanWriteToAssignedFQQN() throws Exception {
+      doTestSenderCanWriteToAssignedFQQN(FQQN_SENDER_2, FQQN_2);
+   }
+
+   private void doTestSenderCanWriteToAssignedFQQN(String username, String 
fqqn) throws Exception {
+      final AmqpClient client = createAmqpClient(username, PASS);
+      final AmqpConnection connection = addConnection(client.connect());
+      final AmqpSession session = connection.createSession();
+      final AmqpSender sender = session.createSender(fqqn);
+
+      final AmqpMessage message = new AmqpMessage();
+      message.setText("Test-Message");
+
+      sender.send(message);
+
+      final Queue queue = getProxyToQueue(fqqn);
+      assertNotNull(queue);
+
+      Wait.assertEquals(1, queue::getMessageCount);
+   }
+
+   @Test
+   public void testReceiver1CanReadFromAssignedFQQN() throws Exception {
+      doTestReceiverCanReadFromAssignedFQQN(FQQN_SENDER_1, FQQN_RECEIVER_1, 
FQQN_1);
+   }
+
+   @Test
+   public void testReceiver2CanReadFromAssignedFQQN() throws Exception {
+      doTestReceiverCanReadFromAssignedFQQN(FQQN_SENDER_2, FQQN_RECEIVER_2, 
FQQN_2);
+   }
+
+   private void doTestReceiverCanReadFromAssignedFQQN(String senderUser, 
String receiverUser, String fqqn) throws Exception {
+      final AmqpClient sendClient = createAmqpClient(senderUser, PASS);
+      final AmqpConnection sendConnection = 
addConnection(sendClient.connect());
+      final AmqpSession sendSession = sendConnection.createSession();
+      final AmqpSender sender = sendSession.createSender(fqqn);
+
+      final AmqpMessage message = new AmqpMessage();
+      message.setText("Test-Message");
+
+      sender.send(message);
+
+      final Queue queue = getProxyToQueue(fqqn);
+      assertNotNull(queue);
+
+      Wait.assertEquals(1, queue::getMessageCount);
+
+      final AmqpClient receiveClient = createAmqpClient(receiverUser, PASS);
+      final AmqpConnection receiveConnection = 
addConnection(receiveClient.connect());
+      final AmqpSession receiveSession = receiveConnection.createSession();
+      final AmqpReceiver receiver = receiveSession.createReceiver(fqqn);
+
+      receiver.flow(1);
+      final AmqpMessage received = receiver.receive();
+      assertNotNull(received);
+      assertEquals("Test-Message", received.getText());
+      received.accept();
+
+      Wait.assertEquals(0, queue::getMessageCount);
+   }
+
+   @Test
+   public void testReceiver1CannotReadFromFQQNAssignedToReceiver2() throws 
Exception {
+      doTestReceiverCannotReadFromFQQNAssignedToAnotherReceiver(FQQN_SENDER_2, 
FQQN_RECEIVER_1, FQQN_2);
+   }
+
+   @Test
+   public void testReceiver2CannotReadFromFQQNAssignedToReceiver1() throws 
Exception {
+      doTestReceiverCannotReadFromFQQNAssignedToAnotherReceiver(FQQN_SENDER_1, 
FQQN_RECEIVER_2, FQQN_1);
+   }
+
+   private void 
doTestReceiverCannotReadFromFQQNAssignedToAnotherReceiver(String senderUser, 
String receiverUser, String fqqn) throws Exception {
+      final AmqpClient sendClient = createAmqpClient(senderUser, PASS);
+      final AmqpConnection sendConnection = 
addConnection(sendClient.connect());
+      final AmqpSession sendSession = sendConnection.createSession();
+      final AmqpSender sender = sendSession.createSender(fqqn);
+
+      final AmqpMessage message = new AmqpMessage();
+      message.setText("Test-Message");
+
+      sender.send(message);
+
+      final Queue queue = getProxyToQueue(fqqn);
+      assertNotNull(queue);
+
+      Wait.assertEquals(1, queue::getMessageCount);
+
+      final AmqpClient receiveClient = createAmqpClient(receiverUser, PASS);
+      final AmqpConnection receiveConnection = 
addConnection(receiveClient.connect());
+      final AmqpSession receiveSession = receiveConnection.createSession();
+
+      try {
+         receiveSession.createReceiver(fqqn);
+         fail("Should not be able to attach to FQQN assigned to another 
user.");
+      } catch (IOException e) {
+         assertNotNull(e.getCause());
+         assertTrue(e.getCause() instanceof JMSSecurityException);
+      }
+
+      Wait.assertEquals(1, queue::getMessageCount);
+   }
+
+   @Test
+   public void testAnonymousSender1CanWriteToAssignedFQQN() throws Exception {
+      doTestAnonymousSendersCanWriteToAssignedFQQN(FQQN_SENDER_1, FQQN_1);
+   }
+
+   @Test
+   public void testAnonymousSenders2CanWriteToAssignedFQQN() throws Exception {
+      doTestAnonymousSendersCanWriteToAssignedFQQN(FQQN_SENDER_2, FQQN_2);
+   }
+
+   private void doTestAnonymousSendersCanWriteToAssignedFQQN(String username, 
String fqqn) throws Exception {
+      final AmqpClient client = createAmqpClient(username, PASS);
+      final AmqpConnection connection = addConnection(client.connect());
+      final AmqpSession session = connection.createSession();
+      final AmqpSender sender = session.createSender();
+
+      final AmqpMessage message = new AmqpMessage();
+      message.setText("Test-Message");
+      message.setAddress(fqqn);
+
+      sender.send(message);
+
+      final Queue queue = getProxyToQueue(fqqn);
+      assertNotNull(queue);
+
+      Wait.assertEquals(1, queue::getMessageCount);
+   }
+
+   @Test
+   public void testSender1CannotAttachToUnassignedFQQN() throws Exception {
+      doTestSendersCannotAttachToUnassignedFQQN(FQQN_SENDER_1, FQQN_2);
+   }
+
+   @Test
+   public void testSender2CannotAttachToUnassignedFQQN() throws Exception {
+      doTestSendersCannotAttachToUnassignedFQQN(FQQN_SENDER_2, FQQN_1);
+   }
+
+   private void doTestSendersCannotAttachToUnassignedFQQN(String username, 
String fqqn) throws Exception {
+      final AmqpClient client = createAmqpClient(username, PASS);
+      final AmqpConnection connection = addConnection(client.connect());
+      final AmqpSession session = connection.createSession();
+
+      try {
+         session.createSender(fqqn);
+         fail("Should not be able to attach to FQQN assigned to another 
user.");
+      } catch (IOException e) {
+         assertNotNull(e.getCause());
+         assertTrue(e.getCause() instanceof JMSSecurityException);
+      }
+   }
+
+   @Test
+   public void testAnonymousSender1CannotWriteToUnassignedFQQN() throws 
Exception {
+      doTestAnonymousSendersCannotWriteToUnassignedFQQN(FQQN_SENDER_1, FQQN_2);
+   }
+
+   @Test
+   public void testAnonymousSender2CannotWriteToUnassignedFQQN() throws 
Exception {
+      doTestAnonymousSendersCannotWriteToUnassignedFQQN(FQQN_SENDER_2, FQQN_1);
+   }
+
+   private void doTestAnonymousSendersCannotWriteToUnassignedFQQN(String 
username, String fqqn) throws Exception {
+      final AmqpClient client = createAmqpClient(username, PASS);
+      final AmqpConnection connection = addConnection(client.connect());
+      final AmqpSession session = connection.createSession();
+      final AmqpSender sender = session.createSender();
+
+      final AmqpMessage message = new AmqpMessage();
+      message.setText("Test-Message");
+      message.setAddress(fqqn);
+
+      try {
+         sender.send(message);
+         fail("Should not be able to send to FQQN assigned to another user.");
+      } catch (IOException e) {
+         assertNotNull(e.getCause());
+         assertTrue(e.getCause() instanceof JMSSecurityException);
+      }
+   }
+
+   @Test
+   public void testReceiver1CannotAttachAsSenderToEitherFQQN() throws 
Exception {
+      doTestReceiverCannotAttachAsSenderToEitherFQQN(FQQN_RECEIVER_1);
+   }
+
+   @Test
+   public void testReceiver2CannotAttachAsSenderToEitherFQQN() throws 
Exception {
+      doTestReceiverCannotAttachAsSenderToEitherFQQN(FQQN_RECEIVER_1);

Review Comment:
   Arg should be FQQN_RECEIVER_2





Issue Time Tracking
-------------------

    Worklog Id:     (was: 928599)
    Time Spent: 0.5h  (was: 20m)

> FQQN Security settings not honored when an AMQP Sender attaches
> ---------------------------------------------------------------
>
>                 Key: ARTEMIS-4969
>                 URL: https://issues.apache.org/jira/browse/ARTEMIS-4969
>             Project: ActiveMQ Artemis
>          Issue Type: Bug
>          Components: AMQP
>    Affects Versions: 2.36.0
>            Reporter: Timothy A. Bish
>            Assignee: Timothy A. Bish
>            Priority: Major
>             Fix For: 2.37.0
>
>          Time Spent: 0.5h
>  Remaining Estimate: 0h
>
> When an AMQP sender link is attaching with an FQQN in the target address the 
> initialization code is not checking fully if the sender has specifically 
> granted FQQN access and can fail the attach in error.  Instead of just 
> checking the FQQN address portion of the target addres both the FQQN address 
> and queue should be checked with the security store so that the link attach 
> can complete when authorized.  This was addressed for Core clients in 
> ARTEMIS-4580



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@activemq.apache.org
For additional commands, e-mail: issues-h...@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact


Reply via email to