Search in sources :

Example 16 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class AbstractVertxBasedMqttProtocolAdapterTest method testUploadTelemetryMessageFailsForDisabledTenant.

/**
 * Verifies that the adapter does not forward a message published by a device
 * if the device belongs to a tenant for which the adapter has been disabled.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testUploadTelemetryMessageFailsForDisabledTenant(final TestContext ctx) {
    // GIVEN an adapter
    final MqttServer server = getMqttServer(false);
    // which is disabled for tenant "my-tenant"
    final TenantObject myTenantConfig = TenantObject.from("my-tenant", true);
    myTenantConfig.addAdapterConfiguration(new JsonObject().put(TenantConstants.FIELD_ADAPTERS_TYPE, ADAPTER_TYPE).put(TenantConstants.FIELD_ENABLED, false));
    when(tenantClient.get("my-tenant")).thenReturn(Future.succeededFuture(myTenantConfig));
    final AbstractVertxBasedMqttProtocolAdapter<ProtocolAdapterProperties> adapter = getAdapter(server);
    forceClientMocksToConnected();
    final MessageSender sender = mock(MessageSender.class);
    when(messagingClient.getOrCreateTelemetrySender(anyString())).thenReturn(Future.succeededFuture(sender));
    // WHEN a device of "my-tenant" publishes a telemetry message
    adapter.uploadTelemetryMessage(new MqttContext(mock(MqttPublishMessage.class), mock(MqttEndpoint.class)), "my-tenant", "the-device", Buffer.buffer("test")).setHandler(ctx.asyncAssertFailure(t -> {
        // THEN the message has not been sent downstream
        verify(sender, never()).send(any(Message.class));
        // because the tenant is not enabled
        ctx.assertEquals(HttpURLConnection.HTTP_FORBIDDEN, ((ClientErrorException) t).getErrorCode());
    }));
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) HttpURLConnection(java.net.HttpURLConnection) TestContext(io.vertx.ext.unit.TestContext) Async(io.vertx.ext.unit.Async) MqttQoS(io.netty.handler.codec.mqtt.MqttQoS) ArgumentMatchers(org.mockito.ArgumentMatchers) ProtonDelivery(io.vertx.proton.ProtonDelivery) MqttConnectReturnCode(io.netty.handler.codec.mqtt.MqttConnectReturnCode) TenantConstants(org.eclipse.hono.util.TenantConstants) RunWith(org.junit.runner.RunWith) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) MqttPublishMessage(io.vertx.mqtt.messages.MqttPublishMessage) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Context(io.vertx.core.Context) MqttServer(io.vertx.mqtt.MqttServer) Assert.assertThat(org.junit.Assert.assertThat) TelemetryConstants(org.eclipse.hono.util.TelemetryConstants) ArgumentCaptor(org.mockito.ArgumentCaptor) TenantClient(org.eclipse.hono.client.TenantClient) MessageSender(org.eclipse.hono.client.MessageSender) BiConsumer(java.util.function.BiConsumer) Timeout(org.junit.rules.Timeout) Message(org.apache.qpid.proton.message.Message) RegistrationClient(org.eclipse.hono.client.RegistrationClient) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) JsonObject(io.vertx.core.json.JsonObject) AsyncResult(io.vertx.core.AsyncResult) HonoClient(org.eclipse.hono.client.HonoClient) Before(org.junit.Before) ProtocolAdapterProperties(org.eclipse.hono.config.ProtocolAdapterProperties) AfterClass(org.junit.AfterClass) UsernamePasswordCredentials(org.eclipse.hono.service.auth.device.UsernamePasswordCredentials) DeviceCredentials(org.eclipse.hono.service.auth.device.DeviceCredentials) Vertx(io.vertx.core.Vertx) RegistrationConstants(org.eclipse.hono.util.RegistrationConstants) Test(org.junit.Test) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) EventConstants(org.eclipse.hono.util.EventConstants) Future(io.vertx.core.Future) TenantObject(org.eclipse.hono.util.TenantObject) TimeUnit(java.util.concurrent.TimeUnit) Mockito(org.mockito.Mockito) HonoClientBasedAuthProvider(org.eclipse.hono.service.auth.device.HonoClientBasedAuthProvider) Rule(org.junit.Rule) Buffer(io.vertx.core.buffer.Buffer) MqttAuth(io.vertx.mqtt.MqttAuth) Device(org.eclipse.hono.service.auth.device.Device) Handler(io.vertx.core.Handler) ProtocolAdapterProperties(org.eclipse.hono.config.ProtocolAdapterProperties) TenantObject(org.eclipse.hono.util.TenantObject) MqttPublishMessage(io.vertx.mqtt.messages.MqttPublishMessage) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) MessageSender(org.eclipse.hono.client.MessageSender) MqttServer(io.vertx.mqtt.MqttServer) JsonObject(io.vertx.core.json.JsonObject) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Test(org.junit.Test)

Example 17 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class EventSenderImpl method sendMessage.

@Override
protected Future<ProtonDelivery> sendMessage(final Message message) {
    Objects.requireNonNull(message);
    final Future<ProtonDelivery> result = Future.future();
    final String messageId = String.format("%s-%d", getClass().getSimpleName(), MESSAGE_COUNTER.getAndIncrement());
    message.setMessageId(messageId);
    sender.send(message, deliveryUpdated -> {
        if (deliveryUpdated.remotelySettled()) {
            if (Accepted.class.isInstance(deliveryUpdated.getRemoteState())) {
                LOG.trace("event [message ID: {}] accepted by peer", messageId);
                result.complete(deliveryUpdated);
            } else if (Rejected.class.isInstance(deliveryUpdated.getRemoteState())) {
                Rejected rejected = (Rejected) deliveryUpdated.getRemoteState();
                if (rejected.getError() == null) {
                    LOG.debug("event [message ID: {}] rejected by peer", messageId);
                    result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
                } else {
                    LOG.debug("event [message ID: {}] rejected by peer: {}, {}", messageId, rejected.getError().getCondition(), rejected.getError().getDescription());
                    result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, rejected.getError().getDescription()));
                }
            } else {
                LOG.debug("event [message ID: {}] not accepted by peer: {}", messageId, deliveryUpdated.getRemoteState());
                result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
            }
        } else {
            LOG.warn("peer did not settle event, failing delivery [new remote state: {}]", deliveryUpdated.getRemoteState());
            result.fail(new ServerErrorException(HttpURLConnection.HTTP_INTERNAL_ERROR));
        }
    });
    LOG.trace("sent event [ID: {}], remaining credit: {}, queued messages: {}", messageId, sender.getCredit(), sender.getQueued());
    return result;
}
Also used : ProtonDelivery(io.vertx.proton.ProtonDelivery) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ServerErrorException(org.eclipse.hono.client.ServerErrorException)

Example 18 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class AbstractVertxBasedHttpProtocolAdapterTest method testUploadEventFailsForRejectedOutcome.

/**
 * Verifies that the adapter fails the upload of an event with a 400
 * result if it is rejected by the downstream peer.
 */
@Test
public void testUploadEventFailsForRejectedOutcome() {
    // GIVEN an adapter with a downstream event consumer attached
    final Future<ProtonDelivery> outcome = Future.future();
    givenAnEventSenderForOutcome(outcome);
    HttpServer server = getHttpServer(false);
    AbstractVertxBasedHttpProtocolAdapter<HttpProtocolAdapterProperties> adapter = getAdapter(server, null);
    // WHEN a device publishes an event that is not accepted by the peer
    final Buffer payload = Buffer.buffer("some payload");
    final RoutingContext ctx = newRoutingContext(payload);
    adapter.uploadEventMessage(ctx, "tenant", "device", payload, "application/text");
    outcome.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "malformed message"));
    // THEN the device gets a 400
    verify(ctx).fail(HttpURLConnection.HTTP_BAD_REQUEST);
}
Also used : Buffer(io.vertx.core.buffer.Buffer) RoutingContext(io.vertx.ext.web.RoutingContext) ProtonDelivery(io.vertx.proton.ProtonDelivery) HttpServer(io.vertx.core.http.HttpServer) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Test(org.junit.Test)

Example 19 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class AbstractVertxBasedMqttProtocolAdapter method handleEndpointConnectionWithAuthentication.

private void handleEndpointConnectionWithAuthentication(final MqttEndpoint endpoint) {
    if (endpoint.auth() == null) {
        LOG.debug("connection request from device [clientId: {}] rejected: {}", endpoint.clientIdentifier(), "device did not provide credentials in CONNECT packet");
        endpoint.reject(MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD);
    } else {
        final DeviceCredentials credentials = getCredentials(endpoint.auth());
        if (credentials == null) {
            LOG.debug("connection request from device [clientId: {}] rejected: {}", endpoint.clientIdentifier(), "device provided malformed credentials in CONNECT packet");
            endpoint.reject(MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD);
        } else {
            getTenantConfiguration(credentials.getTenantId()).compose(tenantConfig -> {
                if (tenantConfig.isAdapterEnabled(getTypeName())) {
                    LOG.debug("protocol adapter [{}] is enabled for tenant [{}]", getTypeName(), credentials.getTenantId());
                    return Future.succeededFuture(tenantConfig);
                } else {
                    LOG.debug("protocol adapter [{}] is disabled for tenant [{}]", getTypeName(), credentials.getTenantId());
                    return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN, "adapter disabled for tenant"));
                }
            }).compose(tenantConfig -> {
                final Future<Device> result = Future.future();
                getCredentialsAuthProvider().authenticate(credentials, result.completer());
                return result;
            }).map(authenticatedDevice -> {
                LOG.debug("successfully authenticated device [tenant-id: {}, auth-id: {}, device-id: {}]", authenticatedDevice.getTenantId(), credentials.getAuthId(), authenticatedDevice.getDeviceId());
                onAuthenticationSuccess(endpoint, authenticatedDevice);
                return null;
            }).otherwise(t -> {
                LOG.debug("cannot authenticate device [tenant-id: {}, auth-id: {}]", credentials.getTenantId(), credentials.getAuthId(), t);
                if (ServerErrorException.class.isInstance(t)) {
                    // one of the services we depend on might not be available (yet)
                    endpoint.reject(MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE);
                } else {
                    // validation of credentials has failed
                    endpoint.reject(MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED);
                }
                return null;
            });
        }
    }
}
Also used : HttpURLConnection(java.net.HttpURLConnection) MqttQoS(io.netty.handler.codec.mqtt.MqttQoS) MqttConnectReturnCode(io.netty.handler.codec.mqtt.MqttConnectReturnCode) LoggerFactory(org.slf4j.LoggerFactory) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) Autowired(org.springframework.beans.factory.annotation.Autowired) ClientErrorException(org.eclipse.hono.client.ClientErrorException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) Constants(org.eclipse.hono.util.Constants) MqttServer(io.vertx.mqtt.MqttServer) CompositeFuture(io.vertx.core.CompositeFuture) TelemetryConstants(org.eclipse.hono.util.TelemetryConstants) MessageSender(org.eclipse.hono.client.MessageSender) AbstractProtocolAdapterBase(org.eclipse.hono.service.AbstractProtocolAdapterBase) Message(org.apache.qpid.proton.message.Message) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) JsonObject(io.vertx.core.json.JsonObject) ProtocolAdapterProperties(org.eclipse.hono.config.ProtocolAdapterProperties) UsernamePasswordCredentials(org.eclipse.hono.service.auth.device.UsernamePasswordCredentials) Logger(org.slf4j.Logger) MqttServerOptions(io.vertx.mqtt.MqttServerOptions) DeviceCredentials(org.eclipse.hono.service.auth.device.DeviceCredentials) ServerErrorException(org.eclipse.hono.client.ServerErrorException) EndpointType(org.eclipse.hono.util.EndpointType) EventConstants(org.eclipse.hono.util.EventConstants) Future(io.vertx.core.Future) TenantObject(org.eclipse.hono.util.TenantObject) Objects(java.util.Objects) Buffer(io.vertx.core.buffer.Buffer) MqttAuth(io.vertx.mqtt.MqttAuth) Device(org.eclipse.hono.service.auth.device.Device) Device(org.eclipse.hono.service.auth.device.Device) ClientErrorException(org.eclipse.hono.client.ClientErrorException) DeviceCredentials(org.eclipse.hono.service.auth.device.DeviceCredentials)

Example 20 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class AbstractVertxBasedMqttProtocolAdapterTest method testUploadTelemetryMessageFailsForUnknownDevice.

/**
 * Verifies that the adapter does not forward a message published by a device
 * if the device's registration status cannot be asserted.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testUploadTelemetryMessageFailsForUnknownDevice(final TestContext ctx) {
    // GIVEN an adapter
    final MqttServer server = getMqttServer(false);
    final AbstractVertxBasedMqttProtocolAdapter<ProtocolAdapterProperties> adapter = getAdapter(server);
    givenATelemetrySenderForOutcome(Future.succeededFuture(mock(ProtonDelivery.class)));
    // WHEN an unknown device publishes a telemetry message
    when(regClient.assertRegistration(eq("unknown"), any())).thenReturn(Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND)));
    final MessageSender sender = mock(MessageSender.class);
    when(messagingClient.getOrCreateTelemetrySender(anyString())).thenReturn(Future.succeededFuture(sender));
    adapter.uploadTelemetryMessage(new MqttContext(mock(MqttPublishMessage.class), mock(MqttEndpoint.class)), "my-tenant", "unknown", Buffer.buffer("test")).setHandler(ctx.asyncAssertFailure(t -> {
        // THEN the message has not been sent downstream
        verify(sender, never()).send(any(Message.class));
        // because the device's registration status could not be asserted
        ctx.assertEquals(HttpURLConnection.HTTP_NOT_FOUND, ((ClientErrorException) t).getErrorCode());
    }));
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) HttpURLConnection(java.net.HttpURLConnection) TestContext(io.vertx.ext.unit.TestContext) Async(io.vertx.ext.unit.Async) MqttQoS(io.netty.handler.codec.mqtt.MqttQoS) ArgumentMatchers(org.mockito.ArgumentMatchers) ProtonDelivery(io.vertx.proton.ProtonDelivery) MqttConnectReturnCode(io.netty.handler.codec.mqtt.MqttConnectReturnCode) TenantConstants(org.eclipse.hono.util.TenantConstants) RunWith(org.junit.runner.RunWith) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) MqttPublishMessage(io.vertx.mqtt.messages.MqttPublishMessage) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Context(io.vertx.core.Context) MqttServer(io.vertx.mqtt.MqttServer) Assert.assertThat(org.junit.Assert.assertThat) TelemetryConstants(org.eclipse.hono.util.TelemetryConstants) ArgumentCaptor(org.mockito.ArgumentCaptor) TenantClient(org.eclipse.hono.client.TenantClient) MessageSender(org.eclipse.hono.client.MessageSender) BiConsumer(java.util.function.BiConsumer) Timeout(org.junit.rules.Timeout) Message(org.apache.qpid.proton.message.Message) RegistrationClient(org.eclipse.hono.client.RegistrationClient) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) JsonObject(io.vertx.core.json.JsonObject) AsyncResult(io.vertx.core.AsyncResult) HonoClient(org.eclipse.hono.client.HonoClient) Before(org.junit.Before) ProtocolAdapterProperties(org.eclipse.hono.config.ProtocolAdapterProperties) AfterClass(org.junit.AfterClass) UsernamePasswordCredentials(org.eclipse.hono.service.auth.device.UsernamePasswordCredentials) DeviceCredentials(org.eclipse.hono.service.auth.device.DeviceCredentials) Vertx(io.vertx.core.Vertx) RegistrationConstants(org.eclipse.hono.util.RegistrationConstants) Test(org.junit.Test) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) EventConstants(org.eclipse.hono.util.EventConstants) Future(io.vertx.core.Future) TenantObject(org.eclipse.hono.util.TenantObject) TimeUnit(java.util.concurrent.TimeUnit) Mockito(org.mockito.Mockito) HonoClientBasedAuthProvider(org.eclipse.hono.service.auth.device.HonoClientBasedAuthProvider) Rule(org.junit.Rule) Buffer(io.vertx.core.buffer.Buffer) MqttAuth(io.vertx.mqtt.MqttAuth) Device(org.eclipse.hono.service.auth.device.Device) Handler(io.vertx.core.Handler) ProtocolAdapterProperties(org.eclipse.hono.config.ProtocolAdapterProperties) MqttPublishMessage(io.vertx.mqtt.messages.MqttPublishMessage) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) MessageSender(org.eclipse.hono.client.MessageSender) MqttServer(io.vertx.mqtt.MqttServer) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Test(org.junit.Test)

Aggregations

ClientErrorException (org.eclipse.hono.client.ClientErrorException)32 JsonObject (io.vertx.core.json.JsonObject)19 Future (io.vertx.core.Future)16 HttpURLConnection (java.net.HttpURLConnection)16 Handler (io.vertx.core.Handler)14 AsyncResult (io.vertx.core.AsyncResult)13 Objects (java.util.Objects)12 ServerErrorException (org.eclipse.hono.client.ServerErrorException)10 TenantConstants (org.eclipse.hono.util.TenantConstants)9 EventBusService (org.eclipse.hono.service.EventBusService)8 EventBusMessage (org.eclipse.hono.util.EventBusMessage)8 Vertx (io.vertx.core.Vertx)6 Buffer (io.vertx.core.buffer.Buffer)6 ProtonDelivery (io.vertx.proton.ProtonDelivery)6 HonoClient (org.eclipse.hono.client.HonoClient)6 MqttEndpoint (io.vertx.mqtt.MqttEndpoint)5 MqttServer (io.vertx.mqtt.MqttServer)5 Optional (java.util.Optional)5 TimeUnit (java.util.concurrent.TimeUnit)5 Message (org.apache.qpid.proton.message.Message)5