org.apache.qpid.proton.amqp.transport.AmqpError Java Examples

The following examples show how to use org.apache.qpid.proton.amqp.transport.AmqpError. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AbstractProtocolAdapterBase.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Creates an AMQP error condition for an throwable.
 * <p>
 * Non {@link ServiceInvocationException} instances are mapped to {@link AmqpError#PRECONDITION_FAILED}.
 *
 * @param t The throwable to map to an error condition.
 * @return The error condition.
 */
protected final ErrorCondition getErrorCondition(final Throwable t) {
    if (ServiceInvocationException.class.isInstance(t)) {
        final ServiceInvocationException error = (ServiceInvocationException) t;
        switch (error.getErrorCode()) {
        case HttpURLConnection.HTTP_BAD_REQUEST:
            return ProtonHelper.condition(Constants.AMQP_BAD_REQUEST, error.getMessage());
        case HttpURLConnection.HTTP_FORBIDDEN:
            return ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS, error.getMessage());
        case HttpUtils.HTTP_TOO_MANY_REQUESTS:
            return ProtonHelper.condition(AmqpError.RESOURCE_LIMIT_EXCEEDED, error.getMessage());
        default:
            return ProtonHelper.condition(AmqpError.PRECONDITION_FAILED, error.getMessage());
        }
    } else {
        return ProtonHelper.condition(AmqpError.PRECONDITION_FAILED, t.getMessage());
    }
}
 
Example #2
Source File: AuthenticationEndpoint.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
@Override
public final void onLinkAttach(final ProtonConnection con, final ProtonSender sender, final ResourceIdentifier targetResource) {

    if (ProtonQoS.AT_LEAST_ONCE.equals(sender.getRemoteQoS())) {
        final HonoUser user = Constants.getClientPrincipal(con);
        sender.setQoS(ProtonQoS.AT_LEAST_ONCE).open();
        logger.debug("transferring token to client...");
        final Message tokenMsg = ProtonHelper.message(user.getToken());
        MessageHelper.addProperty(tokenMsg, AuthenticationConstants.APPLICATION_PROPERTY_TYPE, AuthenticationConstants.TYPE_AMQP_JWT);
        sender.send(tokenMsg, disposition -> {
            if (disposition.remotelySettled()) {
                logger.debug("successfully transferred auth token to client");
            } else {
                logger.debug("failed to transfer auth token to client");
            }
            sender.close();
        });
    } else {
        onLinkDetach(sender, ProtonHelper.condition(AmqpError.INVALID_FIELD, "supports AT_LEAST_ONCE delivery mode only"));
    }
}
 
Example #3
Source File: AMQPSessionCallback.java    From activemq-artemis with Apache License 2.0 6 votes vote down vote up
@Override
public int sendMessage(MessageReference ref, Message message, ServerConsumer consumer, int deliveryCount) {

   ProtonServerSenderContext plugSender = (ProtonServerSenderContext) consumer.getProtocolContext();

   try {
      return plugSender.deliverMessage(ref, consumer);
   } catch (Exception e) {
      connection.runNow(() -> {
         plugSender.getSender().setCondition(new ErrorCondition(AmqpError.INTERNAL_ERROR, e.getMessage()));
         connection.flush();
      });
      throw new IllegalStateException("Can't deliver message " + e, e);
   }

}
 
Example #4
Source File: AMQPConnectionCallback.java    From activemq-artemis with Apache License 2.0 6 votes vote down vote up
public boolean validateConnection(org.apache.qpid.proton.engine.Connection connection, SASLResult saslResult) {
   remoteContainerId = connection.getRemoteContainer();
   boolean idOK = server.addClientConnection(remoteContainerId, ExtCapability.needUniqueConnection(connection));
   if (!idOK) {
      //https://issues.apache.org/jira/browse/ARTEMIS-728
      Map<Symbol, Object> connProp = new HashMap<>();
      connProp.put(AmqpSupport.CONNECTION_OPEN_FAILED, "true");
      connection.setProperties(connProp);
      connection.getCondition().setCondition(AmqpError.INVALID_FIELD);
      Map<Symbol, Symbol> info = new HashMap<>();
      info.put(AmqpSupport.INVALID_FIELD, AmqpSupport.CONTAINER_ID);
      connection.getCondition().setInfo(info);
      return false;
   }
   registeredConnectionId.set(true);
   return true;
}
 
Example #5
Source File: ProtonServerReceiverContext.java    From activemq-artemis with Apache License 2.0 6 votes vote down vote up
private Rejected createRejected(final Exception e) {
   ErrorCondition condition = new ErrorCondition();

   // Set condition
   if (e instanceof ActiveMQSecurityException) {
      condition.setCondition(AmqpError.UNAUTHORIZED_ACCESS);
   } else if (isAddressFull(e)) {
      condition.setCondition(AmqpError.RESOURCE_LIMIT_EXCEEDED);
   } else {
      condition.setCondition(Symbol.valueOf("failed"));
   }
   condition.setDescription(e.getMessage());

   Rejected rejected = new Rejected();
   rejected.setError(condition);
   return rejected;
}
 
Example #6
Source File: AmqpSupport.java    From qpid-jms with Apache License 2.0 6 votes vote down vote up
/**
 * Given an ErrorCondition instance create a new Exception that best matches
 * the error type that indicates a non-fatal error usually at the link level
 * such as link closed remotely or link create failed due to security access
 * issues.
 *
 * @param provider
 * 		the AMQP provider instance that originates this exception
 * @param endpoint
 *      The target of the error.
 * @param errorCondition
 *      The ErrorCondition returned from the remote peer.
 *
 * @return a new Exception instance that best matches the ErrorCondition value.
 */
public static ProviderException convertToNonFatalException(AmqpProvider provider, Endpoint endpoint, ErrorCondition errorCondition) {
    ProviderException remoteError = null;

    if (errorCondition != null && errorCondition.getCondition() != null) {
        Symbol error = errorCondition.getCondition();
        String message = extractErrorMessage(errorCondition);

        if (error.equals(AmqpError.UNAUTHORIZED_ACCESS)) {
            remoteError = new ProviderSecurityException(message);
        } else if (error.equals(AmqpError.RESOURCE_LIMIT_EXCEEDED)) {
            remoteError = new ProviderResourceAllocationException(message);
        } else if (error.equals(AmqpError.NOT_FOUND)) {
            remoteError = new ProviderInvalidDestinationException(message);
        } else if (error.equals(TransactionErrors.TRANSACTION_ROLLBACK)) {
            remoteError = new ProviderTransactionRolledBackException(message);
        } else {
            remoteError = new ProviderException(message);
        }
    } else if (remoteError == null) {
        remoteError = new ProviderException("Unknown error from remote peer");
    }

    return remoteError;
}
 
Example #7
Source File: AmqpServiceBase.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Closes an expired client connection.
 * <p>
 * A connection is considered expired if the {@link HonoUser#isExpired()} method
 * of the user principal attached to the connection returns {@code true}.
 *
 * @param con The client connection.
 */
protected final void closeExpiredConnection(final ProtonConnection con) {

    if (!con.isDisconnected()) {
        final HonoUser clientPrincipal = Constants.getClientPrincipal(con);
        if (clientPrincipal != null) {
            log.debug("client's [{}] access token has expired, closing connection", clientPrincipal.getName());
            con.disconnectHandler(null);
            con.closeHandler(null);
            con.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS, "access token expired"));
            con.close();
            con.disconnect();
            publishConnectionClosedEvent(con);
        }
    }
}
 
Example #8
Source File: VertxBasedAmqpProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the connection is rejected as the adapter is disabled.
 */
@Test
public void testConnectionFailsIfAdapterIsDisabled() {
    // GIVEN an AMQP adapter that requires devices to authenticate
    config.setAuthenticationRequired(true);
    final VertxBasedAmqpProtocolAdapter adapter = givenAnAmqpAdapter();
    // AND given a tenant for which the AMQP Adapter is disabled
    givenAConfiguredTenant(TEST_TENANT_ID, false);
    // WHEN a device connects
    final Device authenticatedDevice = new Device(TEST_TENANT_ID, TEST_DEVICE);
    final Record record = new RecordImpl();
    record.set(AmqpAdapterConstants.KEY_CLIENT_DEVICE, Device.class, authenticatedDevice);
    final ProtonConnection deviceConnection = mock(ProtonConnection.class);
    when(deviceConnection.attachments()).thenReturn(record);
    adapter.onConnectRequest(deviceConnection);
    @SuppressWarnings("unchecked")
    final ArgumentCaptor<Handler<AsyncResult<ProtonConnection>>> openHandler = ArgumentCaptor
            .forClass(Handler.class);
    verify(deviceConnection).openHandler(openHandler.capture());
    openHandler.getValue().handle(Future.succeededFuture(deviceConnection));
    // THEN the adapter does not accept the incoming connection request. 
    final ArgumentCaptor<ErrorCondition> errorConditionCaptor = ArgumentCaptor.forClass(ErrorCondition.class);
    verify(deviceConnection).setCondition(errorConditionCaptor.capture());
    assertEquals(AmqpError.UNAUTHORIZED_ACCESS, errorConditionCaptor.getValue().getCondition());
}
 
Example #9
Source File: VertxBasedAmqpProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the connection is rejected as the connection limit for 
 * the given tenant is exceeded.
 */
@Test
public void testConnectionFailsIfTenantLevelConnectionLimitIsExceeded() {
    // GIVEN an AMQP adapter that requires devices to authenticate
    config.setAuthenticationRequired(true);
    final VertxBasedAmqpProtocolAdapter adapter = givenAnAmqpAdapter();
    // WHEN the connection limit for the given tenant exceeds
    when(resourceLimitChecks.isConnectionLimitReached(any(TenantObject.class), any(SpanContext.class)))
            .thenReturn(Future.succeededFuture(Boolean.TRUE));
    // WHEN a device connects
    final Device authenticatedDevice = new Device(TEST_TENANT_ID, TEST_DEVICE);
    final Record record = new RecordImpl();
    record.set(AmqpAdapterConstants.KEY_CLIENT_DEVICE, Device.class, authenticatedDevice);
    final ProtonConnection deviceConnection = mock(ProtonConnection.class);
    when(deviceConnection.attachments()).thenReturn(record);
    adapter.onConnectRequest(deviceConnection);
    @SuppressWarnings("unchecked")
    final ArgumentCaptor<Handler<AsyncResult<ProtonConnection>>> openHandler = ArgumentCaptor
            .forClass(Handler.class);
    verify(deviceConnection).openHandler(openHandler.capture());
    openHandler.getValue().handle(Future.succeededFuture(deviceConnection));
    // THEN the adapter does not accept the incoming connection request. 
    final ArgumentCaptor<ErrorCondition> errorConditionCaptor = ArgumentCaptor.forClass(ErrorCondition.class);
    verify(deviceConnection).setCondition(errorConditionCaptor.capture());
    assertEquals(AmqpError.UNAUTHORIZED_ACCESS, errorConditionCaptor.getValue().getCondition());
}
 
Example #10
Source File: MappingAndDelegatingCommandHandlerTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that a command message with an address that contains a tenant which doesn't
 * match the scope of the command receiver link gets rejected.
 */
@SuppressWarnings("unchecked")
@Test
public void testMapForMessageHavingAddressWithInvalidTenant() {

    // GIVEN a command message with an address that contains an
    // invalid tenant
    final String deviceId = "4711";
    final Message message = getValidCommandMessage(deviceId);
    message.setAddress(String.format("%s/%s/%s", CommandConstants.COMMAND_ENDPOINT, "wrong-tenant", deviceId));

    // WHEN mapping and delegating the command
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    mappingAndDelegatingCommandHandler.mapAndDelegateIncomingCommandMessage(Constants.DEFAULT_TENANT, delivery, message);

    // THEN the disposition is REJECTED
    verify(delivery).disposition(
            argThat(state -> AmqpError.UNAUTHORIZED_ACCESS.equals(((Rejected) state).getError().getCondition())),
            eq(true));
    // and the message is not being delegated
    verify(sender, never()).send(any(Message.class), any(Handler.class));
}
 
Example #11
Source File: AmqpSupportTest.java    From qpid-jms with Apache License 2.0 6 votes vote down vote up
@Test
public void testCreateRedirectionExceptionWithNoNetworkHost() throws URISyntaxException {
    AmqpProvider mockProvider = Mockito.mock(AmqpProvider.class);
    Mockito.when(mockProvider.getRemoteURI()).thenReturn(new URI("amqp://localhost:5672"));

    ErrorCondition condition = new ErrorCondition();

    Map<Symbol, Object> info = new HashMap<>();
    info.put(AmqpSupport.PORT, "5672");
    info.put(AmqpSupport.OPEN_HOSTNAME, "localhost");
    info.put(AmqpSupport.SCHEME, "amqp");
    info.put(AmqpSupport.PATH, "websocket");

    condition.setInfo(info);

    Symbol error = AmqpError.INTERNAL_ERROR;
    String message = "Failed to connect";

    Exception result = AmqpSupport.createRedirectException(mockProvider, error, message, condition);

    assertNotNull(result);
    assertFalse(result instanceof ProviderConnectionRedirectedException);
    assertTrue(result instanceof ProviderException);
}
 
Example #12
Source File: StatusCodeMapper.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Creates an exception for an AMQP error condition.
 *
 * @param condition The error condition.
 * @param description The error description or {@code null} if not available.
 * @return The exception.
 * @throws NullPointerException if error is {@code null}.
 */
public static final ServiceInvocationException from(final Symbol condition, final String description) {

    Objects.requireNonNull(condition);

    if (AmqpError.RESOURCE_LIMIT_EXCEEDED.equals(condition)) {
        return new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN, description);
    } else if (AmqpError.UNAUTHORIZED_ACCESS.equals(condition)) {
        return new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN, description);
    } else if (AmqpError.INTERNAL_ERROR.equals(condition)) {
        return new ServerErrorException(HttpURLConnection.HTTP_INTERNAL_ERROR, description);
    } else if (Constants.AMQP_BAD_REQUEST.equals(condition)) {
        return new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, description);
    } else {
        return new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND, description);
    }
}
 
Example #13
Source File: AmqpSupportTest.java    From qpid-jms with Apache License 2.0 6 votes vote down vote up
@Test
public void testCreateRedirectionExceptionWithEmptyNetworkHost() throws URISyntaxException {
    AmqpProvider mockProvider = Mockito.mock(AmqpProvider.class);
    Mockito.when(mockProvider.getRemoteURI()).thenReturn(new URI("amqp://localhost:5672"));

    ErrorCondition condition = new ErrorCondition();

    Map<Symbol, Object> info = new HashMap<>();
    info.put(AmqpSupport.PORT, "5672");
    info.put(AmqpSupport.NETWORK_HOST, "");
    info.put(AmqpSupport.OPEN_HOSTNAME, "localhost");
    info.put(AmqpSupport.SCHEME, "amqp");
    info.put(AmqpSupport.PATH, "websocket");

    condition.setInfo(info);

    Symbol error = AmqpError.INTERNAL_ERROR;
    String message = "Failed to connect";

    Exception result = AmqpSupport.createRedirectException(mockProvider, error, message, condition);

    assertNotNull(result);
    assertFalse(result instanceof ProviderConnectionRedirectedException);
    assertTrue(result instanceof ProviderException);
}
 
Example #14
Source File: AmqpSupportTest.java    From qpid-jms with Apache License 2.0 6 votes vote down vote up
@Test
public void testCreateRedirectionExceptionWithInvalidPort() throws URISyntaxException {
    AmqpProvider mockProvider = Mockito.mock(AmqpProvider.class);
    Mockito.when(mockProvider.getRemoteURI()).thenReturn(new URI("amqp://localhost:5672"));

    ErrorCondition condition = new ErrorCondition();

    Map<Symbol, Object> info = new HashMap<>();
    info.put(AmqpSupport.PORT, "L5672");
    info.put(AmqpSupport.OPEN_HOSTNAME, "localhost");
    info.put(AmqpSupport.NETWORK_HOST, "localhost");
    info.put(AmqpSupport.SCHEME, "amqp");
    info.put(AmqpSupport.PATH, "websocket");

    condition.setInfo(info);

    Symbol error = AmqpError.INTERNAL_ERROR;
    String message = "Failed to connect";

    Exception result = AmqpSupport.createRedirectException(mockProvider, error, message, condition);

    assertNotNull(result);
    assertFalse(result instanceof ProviderConnectionRedirectedException);
    assertTrue(result instanceof ProviderException);
}
 
Example #15
Source File: AmqpSupportTest.java    From qpid-jms with Apache License 2.0 5 votes vote down vote up
@Test
public void testCreateRedirectionException() throws URISyntaxException {
    ErrorCondition condition = new ErrorCondition();

    AmqpProvider mockProvider = Mockito.mock(AmqpProvider.class);
    Mockito.when(mockProvider.getRemoteURI()).thenReturn(new URI("amqp://localhost:5672"));

    Map<Symbol, Object> info = new HashMap<>();
    info.put(AmqpSupport.PORT, "5672");
    info.put(AmqpSupport.OPEN_HOSTNAME, "localhost.localdomain");
    info.put(AmqpSupport.NETWORK_HOST, "localhost");
    info.put(AmqpSupport.SCHEME, "amqp");
    info.put(AmqpSupport.PATH, "/websocket");

    condition.setInfo(info);

    Symbol error = AmqpError.INTERNAL_ERROR;
    String message = "Failed to connect";

    Exception result = AmqpSupport.createRedirectException(mockProvider, error, message, condition);

    assertNotNull(result);
    assertTrue(result instanceof ProviderConnectionRedirectedException);

    ProviderConnectionRedirectedException pre = (ProviderConnectionRedirectedException) result;

    URI redirection = pre.getRedirectionURI();

    assertEquals(5672, redirection.getPort());
    assertTrue("localhost.localdomain", redirection.getQuery().contains("amqp.vhost=localhost.localdomain"));
    assertEquals("localhost", redirection.getHost());
    assertEquals("amqp", redirection.getScheme());
    assertEquals("/websocket", redirection.getPath());
}
 
Example #16
Source File: AmqpSecurityTest.java    From activemq-artemis with Apache License 2.0 5 votes vote down vote up
@Test(timeout = 60000)
public void testSendAndRejected() throws Exception {
   AmqpClient client = createAmqpClient(guestUser, guestPass);
   client.setValidator(new AmqpValidator() {

      @Override
      public void inspectOpenedResource(Sender sender) {
         ErrorCondition condition = sender.getRemoteCondition();

         if (condition != null && condition.getCondition() != null) {
            if (!condition.getCondition().equals(AmqpError.UNAUTHORIZED_ACCESS)) {
               markAsInvalid("Should have been tagged with unauthorized access error");
            }
         } else {
            markAsInvalid("Sender should have been opened with an error");
         }
      }
   });

   AmqpConnection connection = addConnection(client.connect());
   AmqpSession session = connection.createSession();

   try {
      try {
         session.createSender(getQueueName());
         fail("Should not be able to consume here.");
      } catch (Exception ex) {
         instanceLog.debug("Caught expected exception");
      }

      connection.getStateInspector().assertValid();
   } finally {
      connection.close();
   }
}
 
Example #17
Source File: AmqpSupportTest.java    From qpid-jms with Apache License 2.0 5 votes vote down vote up
@Test
public void testCreateRedirectionExceptionWithNoRedirectInfo() throws URISyntaxException {
    AmqpProvider mockProvider = Mockito.mock(AmqpProvider.class);
    Mockito.when(mockProvider.getRemoteURI()).thenReturn(new URI("amqp://localhost:5672"));

    ErrorCondition condition = new ErrorCondition();
    Symbol error = AmqpError.INTERNAL_ERROR;
    String message = "Failed to connect";

    Exception result = AmqpSupport.createRedirectException(mockProvider, error, message, condition);

    assertNotNull(result);
    assertFalse(result instanceof ProviderConnectionRedirectedException);
    assertTrue(result instanceof ProviderException);
}
 
Example #18
Source File: AmqpSupport.java    From qpid-jms with Apache License 2.0 5 votes vote down vote up
/**
 * Given an ErrorCondition instance create a new Exception that best matches
 * the error type that indicates the connection creation failed for some reason.
 *
 * @param provider
 * 		the AMQP provider instance that originates this exception
 * @param endpoint
 *      The target of the error.
 * @param errorCondition
 *      The ErrorCondition returned from the remote peer.
 *
 * @return a new Exception instance that best matches the ErrorCondition value.
 */
public static ProviderConnectionRemotelyClosedException convertToConnectionClosedException(AmqpProvider provider, Endpoint endpoint, ErrorCondition errorCondition) {
    ProviderConnectionRemotelyClosedException remoteError = null;

    if (errorCondition != null && errorCondition.getCondition() != null) {
        Symbol error = errorCondition.getCondition();
        String message = extractErrorMessage(errorCondition);

        if (error.equals(AmqpError.UNAUTHORIZED_ACCESS)) {
            remoteError = new ProviderConnectionSecurityException(message);
        } else if (error.equals(AmqpError.RESOURCE_LIMIT_EXCEEDED)) {
            remoteError = new ProviderConnectionResourceAllocationException(message);
        } else if (error.equals(ConnectionError.CONNECTION_FORCED)) {
            remoteError = new ProviderConnectionRemotelyClosedException(message);
        } else if (error.equals(AmqpError.NOT_FOUND)) {
            remoteError = new ProviderConnectionResourceNotFoundException(message);
        } else if (error.equals(ConnectionError.REDIRECT)) {
            remoteError = createRedirectException(provider, error, message, errorCondition);
        } else if (error.equals(AmqpError.INVALID_FIELD)) {
            Map<?, ?> info = errorCondition.getInfo();
            if (info != null && CONTAINER_ID.equals(info.get(INVALID_FIELD))) {
                remoteError = new ProviderInvalidClientIDException(message);
            } else {
                remoteError = new ProviderConnectionRemotelyClosedException(message);
            }
        } else {
            remoteError = new ProviderConnectionRemotelyClosedException(message);
        }
    } else if (remoteError == null) {
        remoteError = new ProviderConnectionRemotelyClosedException("Unknown error from remote peer");
    }

    return remoteError;
}
 
Example #19
Source File: ProtonHandler.java    From activemq-artemis with Apache License 2.0 5 votes vote down vote up
private void internalHandlerError(Exception e) {
   log.warn(e.getMessage(), e);
   ErrorCondition error = new ErrorCondition();
   error.setCondition(AmqpError.INTERNAL_ERROR);
   error.setDescription("Unrecoverable error: " + (e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage()));
   connection.setCondition(error);
   connection.close();
   flush();
}
 
Example #20
Source File: AmqpSecurityTest.java    From activemq-artemis with Apache License 2.0 5 votes vote down vote up
@Test(timeout = 30000)
public void testConsumerNotAuthorizedToCreateQueues() throws Exception {
   AmqpClient client = createAmqpClient(noprivUser, noprivPass);
   client.setValidator(new AmqpValidator() {

      @Override
      public void inspectOpenedResource(Sender sender) {
         ErrorCondition condition = sender.getRemoteCondition();

         if (condition != null && condition.getCondition() != null) {
            if (!condition.getCondition().equals(AmqpError.UNAUTHORIZED_ACCESS)) {
               markAsInvalid("Should have been tagged with unauthorized access error");
            }
         } else {
            markAsInvalid("Sender should have been opened with an error");
         }
      }
   });

   AmqpConnection connection = client.connect();

   try {
      AmqpSession session = connection.createSession();

      try {
         session.createReceiver(getQueueName(getPrecreatedQueueSize() + 1));
         fail("Should not be able to consume here.");
      } catch (Exception ex) {
         instanceLog.debug("Caught expected exception");
      }

      connection.getStateInspector().assertValid();
   } finally {
      connection.close();
   }
}
 
Example #21
Source File: AmqpSecurityTest.java    From activemq-artemis with Apache License 2.0 5 votes vote down vote up
@Test(timeout = 30000)
public void testReceiverNotAuthorized() throws Exception {
   AmqpClient client = createAmqpClient(noprivUser, noprivPass);
   client.setValidator(new AmqpValidator() {

      @Override
      public void inspectOpenedResource(Receiver receiver) {
         ErrorCondition condition = receiver.getRemoteCondition();

         if (condition != null && condition.getCondition() != null) {
            if (!condition.getCondition().equals(AmqpError.UNAUTHORIZED_ACCESS)) {
               markAsInvalid("Should have been tagged with unauthorized access error");
            }
         } else {
            markAsInvalid("Receiver should have been opened with an error");
         }
      }
   });

   AmqpConnection connection = client.connect();

   try {
      AmqpSession session = connection.createSession();

      try {
         session.createReceiver(getQueueName());
         fail("Should not be able to consume here.");
      } catch (Exception ex) {
         instanceLog.debug("Caught expected exception");
      }

      connection.getStateInspector().assertValid();
   } finally {
      connection.close();
   }
}
 
Example #22
Source File: TransportImpl.java    From qpid-proton-j with Apache License 2.0 5 votes vote down vote up
@Override
public void closed(TransportException error)
{
    if (!_closeReceived || error != null) {
        // Set an error condition, but only if one was not already set
        if(!_conditionSet) {
            if(error instanceof TransportDecodeException) {
                setCondition(new ErrorCondition(AmqpError.DECODE_ERROR, error.getMessage()));
            } else {
                String description =  error == null ? "connection aborted" : error.toString();

                setCondition(new ErrorCondition(ConnectionError.FRAMING_ERROR, description));
            }
        }

        _head_closed = true;
    }

    if (_conditionSet && !postedTransportError) {
        put(Event.Type.TRANSPORT_ERROR, this);
        postedTransportError = true;
    }

    if (!postedTailClosed) {
        put(Event.Type.TRANSPORT_TAIL_CLOSED, this);
        postedTailClosed = true;
        maybePostClosed();
    }
}
 
Example #23
Source File: SimpleAuthenticationServer.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Handles a request from a client to establish a link for receiving messages from this server.
 *
 * @param con the connection to the client.
 * @param sender the sender created for the link.
 */
@Override
protected void handleSenderOpen(final ProtonConnection con, final ProtonSender sender) {

    final Source remoteSource = sender.getRemoteSource();
    LOG.debug("client [{}] wants to open a link for receiving messages [address: {}]",
            con.getRemoteContainer(), remoteSource);
    try {
        final ResourceIdentifier targetResource = getResourceIdentifier(remoteSource.getAddress());
        final AmqpEndpoint endpoint = getEndpoint(targetResource);

        if (endpoint == null) {
            LOG.debug("no endpoint registered for node [{}]", targetResource);
            con.setCondition(ProtonHelper.condition(AmqpError.NOT_FOUND, "no such node")).close();
        } else {
            final HonoUser user = Constants.getClientPrincipal(con);
            if (Constants.SUBJECT_ANONYMOUS.equals(user.getName())) {
                con.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS, "client must authenticate using SASL")).close();
            } else {
                Constants.copyProperties(con, sender);
                sender.setSource(sender.getRemoteSource());
                endpoint.onLinkAttach(con, sender, targetResource);
            }
        }
    } catch (final IllegalArgumentException e) {
        LOG.debug("client has provided invalid resource identifier as source address", e);
        con.setCondition(ProtonHelper.condition(AmqpError.INVALID_FIELD, "malformed source address")).close();
    }
}
 
Example #24
Source File: HonoConnectionImplTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the attempt to create a receiver fails with a
 * {@code ServiceInvocationException} if the remote peer refuses
 * to open the link with an error condition.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateReceiverFailsForErrorCondition(final VertxTestContext ctx) {

    testCreateReceiverFails(ctx, () -> new ErrorCondition(AmqpError.RESOURCE_LIMIT_EXCEEDED, "unauthorized"), cause -> {
        return cause instanceof ServiceInvocationException;
    });
}
 
Example #25
Source File: HonoConnectionImplTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the attempt to create a sender fails with a
 * {@code ServiceInvocationException} if the remote peer refuses
 * to open the link with an error condition.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateSenderFailsForErrorCondition(final VertxTestContext ctx) {

    testCreateSenderFails(
            ctx,
            () -> new ErrorCondition(AmqpError.RESOURCE_LIMIT_EXCEEDED, "unauthorized"),
            cause -> {
                return cause instanceof ServiceInvocationException;
            });
}
 
Example #26
Source File: VertxBasedAmqpProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the connection is rejected as the connection limit for 
 * the adapter is exceeded.
 */
@Test
public void testConnectionFailsIfAdapterLevelConnectionLimitIsExceeded() {
    // GIVEN an AMQP adapter that requires devices to authenticate
    config.setAuthenticationRequired(true);
    final VertxBasedAmqpProtocolAdapter adapter = givenAnAmqpAdapter();
    // WHEN the adapter's connection limit exceeds
    when(connectionLimitManager.isLimitExceeded()).thenReturn(true);
    // WHEN a device connects
    final Device authenticatedDevice = new Device(TEST_TENANT_ID, TEST_DEVICE);
    final Record record = new RecordImpl();
    record.set(AmqpAdapterConstants.KEY_CLIENT_DEVICE, Device.class, authenticatedDevice);
    final ProtonConnection deviceConnection = mock(ProtonConnection.class);
    when(deviceConnection.attachments()).thenReturn(record);
    adapter.onConnectRequest(deviceConnection);
    @SuppressWarnings("unchecked")
    final ArgumentCaptor<Handler<AsyncResult<ProtonConnection>>> openHandler = ArgumentCaptor
            .forClass(Handler.class);
    verify(deviceConnection).openHandler(openHandler.capture());
    openHandler.getValue().handle(Future.succeededFuture(deviceConnection));
    // THEN the connection count should be incremented when the connection is opened
    final InOrder metricsInOrderVerifier = inOrder(metrics);
    metricsInOrderVerifier.verify(metrics).incrementConnections(TEST_TENANT_ID);
    // AND the adapter should close the connection right after it opened it
    final ArgumentCaptor<Handler<AsyncResult<ProtonConnection>>> closeHandler = ArgumentCaptor.forClass(Handler.class);
    verify(deviceConnection).closeHandler(closeHandler.capture());
    closeHandler.getValue().handle(Future.succeededFuture());
    final ArgumentCaptor<ErrorCondition> errorConditionCaptor = ArgumentCaptor.forClass(ErrorCondition.class);
    verify(deviceConnection).setCondition(errorConditionCaptor.capture());
    assertEquals(AmqpError.UNAUTHORIZED_ACCESS, errorConditionCaptor.getValue().getCondition());
    // AND the connection count should be decremented accordingly when the connection is closed
    metricsInOrderVerifier.verify(metrics).decrementConnections(TEST_TENANT_ID);
    verify(metrics).reportConnectionAttempt(ConnectionAttemptOutcome.ADAPTER_CONNECTION_LIMIT_EXCEEDED);
}
 
Example #27
Source File: AmqpServiceBase.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Closes a link for an unknown target address.
 * <p>
 * The link is closed with AMQP error code <em>amqp:not-found</em>.
 *
 * @param con The connection that the link belongs to.
 * @param link The link.
 * @param address The unknown target address.
 */
protected final void handleUnknownEndpoint(final ProtonConnection con, final ProtonLink<?> link, final ResourceIdentifier address) {
    log.info("client [container: {}] wants to establish link for unknown endpoint [address: {}]",
            con.getRemoteContainer(), address);
    link.setCondition(
            ProtonHelper.condition(
                    AmqpError.NOT_FOUND,
                    String.format("no endpoint registered for address %s", address)));
    link.close();
}
 
Example #28
Source File: AmqpServiceBase.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Handles a request from a client to establish a link for sending messages to this server.
 * The already established connection must have an authenticated user as principal for doing the authorization check.
 *
 * @param con the connection to the client.
 * @param receiver the receiver created for the link.
 */
protected void handleReceiverOpen(final ProtonConnection con, final ProtonReceiver receiver) {
    if (receiver.getRemoteTarget().getAddress() == null) {
        log.debug("client [container: {}] wants to open an anonymous link for sending messages to arbitrary addresses, closing link ...",
                con.getRemoteContainer());
        receiver.setCondition(ProtonHelper.condition(AmqpError.NOT_ALLOWED, "anonymous relay not supported"));
        receiver.close();
    } else {
        log.debug("client [container: {}] wants to open a link [address: {}] for sending messages",
                con.getRemoteContainer(), receiver.getRemoteTarget());
        try {
            final ResourceIdentifier targetResource = getResourceIdentifier(receiver.getRemoteTarget().getAddress());
            final AmqpEndpoint endpoint = getEndpoint(targetResource);
            if (endpoint == null) {
                handleUnknownEndpoint(con, receiver, targetResource);
            } else {
                final HonoUser user = Constants.getClientPrincipal(con);
                getAuthorizationService().isAuthorized(user, targetResource, Activity.WRITE).onComplete(authAttempt -> {
                    if (authAttempt.succeeded() && authAttempt.result()) {
                        Constants.copyProperties(con, receiver);
                        receiver.setSource(receiver.getRemoteSource());
                        receiver.setTarget(receiver.getRemoteTarget());
                        endpoint.onLinkAttach(con, receiver, targetResource);
                    } else {
                        log.debug("subject [{}] is not authorized to WRITE to [{}]", user.getName(), targetResource);
                        receiver.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS.toString(), "unauthorized"));
                        receiver.close();
                    }
                });
            }
        } catch (final IllegalArgumentException e) {
            log.debug("client has provided invalid resource identifier as target address", e);
            receiver.setCondition(ProtonHelper.condition(AmqpError.NOT_FOUND, "no such address"));
            receiver.close();
        }
    }
}
 
Example #29
Source File: AmqpServiceBase.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Handles a request from a client to establish a link for receiving messages from this server.
 *
 * @param con the connection to the client.
 * @param sender the sender created for the link.
 */
protected void handleSenderOpen(final ProtonConnection con, final ProtonSender sender) {
    final Source remoteSource = sender.getRemoteSource();
    log.debug("client [container: {}] wants to open a link [address: {}] for receiving messages",
            con.getRemoteContainer(), remoteSource);
    try {
        final ResourceIdentifier targetResource = getResourceIdentifier(remoteSource.getAddress());
        final AmqpEndpoint endpoint = getEndpoint(targetResource);
        if (endpoint == null) {
            handleUnknownEndpoint(con, sender, targetResource);
        } else {
            final HonoUser user = Constants.getClientPrincipal(con);
            getAuthorizationService().isAuthorized(user, targetResource, Activity.READ).onComplete(authAttempt -> {
                if (authAttempt.succeeded() && authAttempt.result()) {
                    Constants.copyProperties(con, sender);
                    sender.setSource(sender.getRemoteSource());
                    sender.setTarget(sender.getRemoteTarget());
                    endpoint.onLinkAttach(con, sender, targetResource);
                } else {
                    log.debug("subject [{}] is not authorized to READ from [{}]", user.getName(), targetResource);
                    sender.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS.toString(), "unauthorized"));
                    sender.close();
                }
            });
        }
    } catch (final IllegalArgumentException e) {
        log.debug("client has provided invalid resource identifier as target address", e);
        sender.setCondition(ProtonHelper.condition(AmqpError.NOT_FOUND, "no such address"));
        sender.close();
    }
}
 
Example #30
Source File: RequestResponseEndpoint.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Handles a client's request to establish a link for sending service invocation requests.
 * <p>
 * Configure and check the receiver link of the endpoint.
 * The remote link of the receiver must not demand the AT_MOST_ONCE QoS (not supported).
 * The receiver link itself is configured with the AT_LEAST_ONCE QoS and grants the configured credits
 * ({@link ServiceConfigProperties#getReceiverLinkCredit()}) with autoAcknowledge.
 * <p>
 * Handling of request messages is delegated to
 * {@link #handleRequestMessage(ProtonConnection, ProtonReceiver, ResourceIdentifier, ProtonDelivery, Message)}.
 *
 * @param con The AMQP connection that the link is part of.
 * @param receiver The ProtonReceiver that has already been created for this endpoint.
 * @param targetAddress The resource identifier for this endpoint (see {@link ResourceIdentifier} for details).
 */
@Override
public final void onLinkAttach(final ProtonConnection con, final ProtonReceiver receiver, final ResourceIdentifier targetAddress) {

    if (ProtonQoS.AT_MOST_ONCE.equals(receiver.getRemoteQoS())) {
        logger.debug("client wants to use unsupported AT MOST ONCE delivery mode for endpoint [{}], closing link ...", getName());
        receiver.setCondition(ProtonHelper.condition(AmqpError.PRECONDITION_FAILED.toString(), "endpoint requires AT_LEAST_ONCE QoS"));
        receiver.close();
    } else {

        logger.debug("establishing link for receiving request messages from client [{}]", receiver.getName());

        receiver.setQoS(ProtonQoS.AT_LEAST_ONCE);
        receiver.setAutoAccept(true); // settle received messages if the handler succeeds
        receiver.setTarget(receiver.getRemoteTarget());
        receiver.setSource(receiver.getRemoteSource());
        // We do manual flow control, credits are replenished after responses have been sent.
        receiver.setPrefetch(0);

        // set up handlers

        receiver.handler((delivery, message) -> {
            try {
                handleRequestMessage(con, receiver, targetAddress, delivery, message);
            } catch (final Exception ex) {
                logger.warn("error handling message", ex);
                ProtonHelper.released(delivery, true);
            }
        });
        HonoProtonHelper.setCloseHandler(receiver, remoteClose -> onLinkDetach(receiver));
        HonoProtonHelper.setDetachHandler(receiver, remoteDetach -> onLinkDetach(receiver));

        // acknowledge the remote open
        receiver.open();

        // send out initial credits, after opening
        logger.debug("flowing {} credits to client", config.getReceiverLinkCredit());
        receiver.flow(config.getReceiverLinkCredit());
    }
}