Search in sources :

Example 91 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class TelemetryResourceTest method testUploadTelemetryWithQoS0.

/**
 * Verifies that the adapter immediately responds with a 2.04 status if a
 * device publishes telemetry data using a NON message.
 */
@Test
public void testUploadTelemetryWithQoS0() {
    // GIVEN an adapter with a downstream telemetry consumer attached
    givenAnAdapter(properties);
    givenATelemetrySenderForAnyTenant();
    final var resource = givenAResource(adapter);
    // WHEN a device publishes an telemetry message
    final Buffer payload = Buffer.buffer("some payload");
    final CoapExchange coapExchange = newCoapExchange(payload, Type.NON, MediaTypeRegistry.TEXT_PLAIN);
    final Device authenticatedDevice = new Device("tenant", "device");
    final CoapContext context = CoapContext.fromRequest(coapExchange, authenticatedDevice, authenticatedDevice, "device", span);
    resource.handlePostRequest(context);
    // THEN the device gets a response indicating success
    verify(coapExchange).respond(argThat((Response res) -> ResponseCode.CHANGED.equals(res.getCode())));
    // and the message has been forwarded downstream
    assertTelemetryMessageHasBeenSentDownstream(QoS.AT_MOST_ONCE, "tenant", "device", "text/plain");
    verify(metrics).reportTelemetry(eq(MetricsTags.EndpointType.TELEMETRY), eq("tenant"), any(), eq(MetricsTags.ProcessingOutcome.FORWARDED), eq(MetricsTags.QoS.AT_MOST_ONCE), eq(payload.length()), eq(TtdStatus.NONE), any());
}
Also used : Buffer(io.vertx.core.buffer.Buffer) Response(org.eclipse.californium.core.coap.Response) Device(org.eclipse.hono.auth.Device) CoapExchange(org.eclipse.californium.core.server.resources.CoapExchange) Test(org.junit.jupiter.api.Test)

Example 92 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class TelemetryResourceTest method testUploadTelemetryFailsForEmptyBody.

/**
 * Verifies that the adapter fails the upload of an event with a 4.00 result
 * if the request body is empty but is not marked as an empty notification.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testUploadTelemetryFailsForEmptyBody(final VertxTestContext ctx) {
    // GIVEN an adapter
    givenAnAdapter(properties);
    givenATelemetrySenderForAnyTenant();
    final var resource = givenAResource(adapter);
    // WHEN a device publishes an empty message that doesn't contain
    // a URI-query option
    final CoapExchange coapExchange = newCoapExchange(null, Type.NON, MediaTypeRegistry.UNDEFINED);
    final Device authenticatedDevice = new Device("my-tenant", "the-device");
    final CoapContext context = CoapContext.fromRequest(coapExchange, authenticatedDevice, authenticatedDevice, "the-device", span);
    resource.handlePostRequest(context).onComplete(ctx.failing(t -> {
        ctx.verify(() -> {
            // THEN the device gets a response with code 4.00
            assertThat(t).isInstanceOf(ClientErrorException.class);
            assertThat(((ClientErrorException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_BAD_REQUEST);
            // and the message has not been forwarded downstream
            assertNoTelemetryMessageHasBeenSentDownstream();
            verify(metrics, never()).reportTelemetry(any(MetricsTags.EndpointType.class), anyString(), any(), any(MetricsTags.ProcessingOutcome.class), any(MetricsTags.QoS.class), anyInt(), any(TtdStatus.class), any());
        });
        ctx.completeNow();
    }));
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) HttpURLConnection(java.net.HttpURLConnection) ResponseCode(org.eclipse.californium.core.coap.CoAP.ResponseCode) VertxTestContext(io.vertx.junit5.VertxTestContext) CoapExchange(org.eclipse.californium.core.server.resources.CoapExchange) Response(org.eclipse.californium.core.coap.Response) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ArgumentMatchers.argThat(org.mockito.ArgumentMatchers.argThat) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Constants(org.eclipse.hono.util.Constants) Timeout(io.vertx.junit5.Timeout) ProcessingOutcome(org.eclipse.hono.service.metric.MetricsTags.ProcessingOutcome) TtdStatus(org.eclipse.hono.service.metric.MetricsTags.TtdStatus) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) MediaTypeRegistry(org.eclipse.californium.core.coap.MediaTypeRegistry) CommandConstants(org.eclipse.hono.util.CommandConstants) ArgumentMatchers.anyInt(org.mockito.ArgumentMatchers.anyInt) Type(org.eclipse.californium.core.coap.CoAP.Type) Direction(org.eclipse.hono.service.metric.MetricsTags.Direction) NoopTracerFactory(io.opentracing.noop.NoopTracerFactory) Promise(io.vertx.core.Promise) CommandContext(org.eclipse.hono.client.command.CommandContext) MetricsTags(org.eclipse.hono.service.metric.MetricsTags) ServerErrorException(org.eclipse.hono.client.ServerErrorException) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) Sample(io.micrometer.core.instrument.Timer.Sample) VertxExtension(io.vertx.junit5.VertxExtension) EventConstants(org.eclipse.hono.util.EventConstants) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) Mockito.verify(org.mockito.Mockito.verify) TenantObject(org.eclipse.hono.util.TenantObject) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) Mockito.never(org.mockito.Mockito.never) Buffer(io.vertx.core.buffer.Buffer) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) OptionSet(org.eclipse.californium.core.coap.OptionSet) Handler(io.vertx.core.Handler) QoS(org.eclipse.hono.util.QoS) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Mockito.mock(org.mockito.Mockito.mock) Device(org.eclipse.hono.auth.Device) ClientErrorException(org.eclipse.hono.client.ClientErrorException) MetricsTags(org.eclipse.hono.service.metric.MetricsTags) CoapExchange(org.eclipse.californium.core.server.resources.CoapExchange) Test(org.junit.jupiter.api.Test)

Example 93 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class CommandResponseResource method uploadCommandResponseMessage.

/**
 * Forwards a command response to a downstream application.
 *
 * @param context The context representing the command response to be forwarded.
 * @return A future indicating the outcome of the operation.
 *         The future will be succeeded if the message has been forwarded successfully.
 *         In this case one of the context's <em>respond</em> methods will have been invoked to send a CoAP response
 *         back to the device.
 *         Otherwise the future will be failed with a {@link org.eclipse.hono.client.ServiceInvocationException}.
 * @throws NullPointerException if context is {@code null}.
 */
public final Future<Void> uploadCommandResponseMessage(final CoapContext context) {
    Objects.requireNonNull(context);
    final Device device = context.getOriginDevice();
    final Device authenticatedDevice = context.getAuthenticatedDevice();
    if (!context.isConfirmable()) {
        return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "command response endpoint supports confirmable request messages only"));
    }
    final Buffer payload = context.getPayload();
    final String contentType = context.getContentType();
    final String commandRequestId = context.getCommandRequestId();
    final Integer responseStatus = context.getCommandResponseStatus();
    LOG.debug("processing response to command [tenantId: {}, deviceId: {}, cmd-req-id: {}, status code: {}]", device.getTenantId(), device.getDeviceId(), commandRequestId, responseStatus);
    final Span currentSpan = TracingHelper.buildChildSpan(getTracer(), context.getTracingContext(), "upload Command response", getAdapter().getTypeName()).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).withTag(TracingHelper.TAG_TENANT_ID, device.getTenantId()).withTag(TracingHelper.TAG_DEVICE_ID, device.getDeviceId()).withTag(Constants.HEADER_COMMAND_RESPONSE_STATUS, responseStatus).withTag(Constants.HEADER_COMMAND_REQUEST_ID, commandRequestId).withTag(TracingHelper.TAG_AUTHENTICATED.getKey(), authenticatedDevice != null).start();
    final Future<RegistrationAssertion> deviceRegistrationTracker = getAdapter().getRegistrationAssertion(device.getTenantId(), device.getDeviceId(), authenticatedDevice, currentSpan.context());
    final Future<TenantObject> tenantTracker = getAdapter().getTenantClient().get(device.getTenantId(), currentSpan.context());
    final Optional<CommandResponse> cmdResponse = Optional.ofNullable(CommandResponse.fromRequestId(commandRequestId, device.getTenantId(), device.getDeviceId(), payload, contentType, responseStatus));
    final Future<CommandResponse> commandResponseTracker = cmdResponse.map(res -> Future.succeededFuture(res)).orElseGet(() -> Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, String.format("command-request-id [%s] or status code [%s] is missing/invalid", commandRequestId, responseStatus))));
    return CompositeFuture.all(tenantTracker, commandResponseTracker, deviceRegistrationTracker).compose(ok -> CompositeFuture.all(getAdapter().isAdapterEnabled(tenantTracker.result()), getAdapter().checkMessageLimit(tenantTracker.result(), payload.length(), currentSpan.context())).mapEmpty()).compose(ok -> getAdapter().getCommandResponseSender(commandResponseTracker.result().getMessagingType(), tenantTracker.result()).sendCommandResponse(tenantTracker.result(), deviceRegistrationTracker.result(), commandResponseTracker.result(), currentSpan.context())).onSuccess(ok -> {
        LOG.trace("forwarded command response [command-request-id: {}] to downstream application", commandRequestId);
        currentSpan.log("forwarded command response to application");
        getAdapter().getMetrics().reportCommand(Direction.RESPONSE, device.getTenantId(), tenantTracker.result(), ProcessingOutcome.FORWARDED, payload.length(), context.getTimer());
        context.respondWithCode(ResponseCode.CHANGED);
    }).onFailure(t -> {
        LOG.debug("could not send command response [command-request-id: {}] to application", commandRequestId, t);
        TracingHelper.logError(currentSpan, t);
        getAdapter().getMetrics().reportCommand(Direction.RESPONSE, device.getTenantId(), tenantTracker.result(), ProcessingOutcome.from(t), payload.length(), context.getTimer());
    }).onComplete(r -> currentSpan.finish());
}
Also used : Buffer(io.vertx.core.buffer.Buffer) HttpURLConnection(java.net.HttpURLConnection) ResponseCode(org.eclipse.californium.core.coap.CoAP.ResponseCode) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) Direction(org.eclipse.hono.service.metric.MetricsTags.Direction) LoggerFactory(org.slf4j.LoggerFactory) Vertx(io.vertx.core.Vertx) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Constants(org.eclipse.hono.util.Constants) Tags(io.opentracing.tag.Tags) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) CommandResponse(org.eclipse.hono.client.command.CommandResponse) TenantObject(org.eclipse.hono.util.TenantObject) Objects(java.util.Objects) ProcessingOutcome(org.eclipse.hono.service.metric.MetricsTags.ProcessingOutcome) CompositeFuture(io.vertx.core.CompositeFuture) Buffer(io.vertx.core.buffer.Buffer) Optional(java.util.Optional) Span(io.opentracing.Span) TracingHelper(org.eclipse.hono.tracing.TracingHelper) CommandConstants(org.eclipse.hono.util.CommandConstants) Device(org.eclipse.hono.auth.Device) CommandResponse(org.eclipse.hono.client.command.CommandResponse) Span(io.opentracing.Span) TenantObject(org.eclipse.hono.util.TenantObject) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ClientErrorException(org.eclipse.hono.client.ClientErrorException)

Example 94 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class DeviceRegistryBasedCertificateVerifier method validateCertificateAndLoadDevice.

/**
 * Validates a device's client certificate and completes the DTLS handshake result handler.
 *
 * @param cid the connection id to report the result.
 * @param certPath certificate path.
 * @param session session.
 * @see #setResultHandler(HandshakeResultHandler)
 */
private void validateCertificateAndLoadDevice(final ConnectionId cid, final CertPath certPath, final DTLSSession session) {
    LOG.debug("validating client's X.509 certificate");
    final Span span = tracer.buildSpan("validate client certificate").withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).withTag(Tags.COMPONENT.getKey(), adapter.getTypeName()).start();
    validateCertificateAndLoadDevice(session, certPath, span).map(info -> {
        // set AdditionalInfo as customArgument here
        return new CertificateVerificationResult(cid, certPath, info);
    }).otherwise(t -> {
        TracingHelper.logError(span, "could not validate X509 for device", t);
        LOG.debug("error validating X509", t);
        final AlertMessage alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.BAD_CERTIFICATE, session.getPeer());
        return new CertificateVerificationResult(cid, new HandshakeException("error validating X509", alert), null);
    }).onSuccess(result -> {
        span.finish();
        californiumResultHandler.apply(result);
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) X509Certificate(java.security.cert.X509Certificate) X500Principal(javax.security.auth.x500.X500Principal) LoggerFactory(org.slf4j.LoggerFactory) CertificateType(org.eclipse.californium.scandium.dtls.CertificateType) ClientErrorException(org.eclipse.hono.client.ClientErrorException) AlertDescription(org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription) Tags(io.opentracing.tag.Tags) CertificateMessage(org.eclipse.californium.scandium.dtls.CertificateMessage) ServerName(org.eclipse.californium.scandium.util.ServerName) DeviceCredentials(org.eclipse.hono.adapter.auth.device.DeviceCredentials) HandshakeException(org.eclipse.californium.scandium.dtls.HandshakeException) CertPathUtil(org.eclipse.californium.elements.util.CertPathUtil) ServerNames(org.eclipse.californium.scandium.util.ServerNames) StreamSupport(java.util.stream.StreamSupport) NewAdvancedCertificateVerifier(org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier) TracingHelper(org.eclipse.hono.tracing.TracingHelper) X509Authentication(org.eclipse.hono.adapter.auth.device.X509Authentication) Logger(org.slf4j.Logger) NameType(org.eclipse.californium.scandium.util.ServerName.NameType) Tracer(io.opentracing.Tracer) TenantServiceBasedX509Authentication(org.eclipse.hono.adapter.auth.device.TenantServiceBasedX509Authentication) AlertLevel(org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel) AdditionalInfo(org.eclipse.californium.elements.auth.AdditionalInfo) Promise(io.vertx.core.Promise) HandshakeResultHandler(org.eclipse.californium.scandium.dtls.HandshakeResultHandler) CertPath(java.security.cert.CertPath) Collectors(java.util.stream.Collectors) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) Objects(java.util.Objects) DTLSSession(org.eclipse.californium.scandium.dtls.DTLSSession) List(java.util.List) Certificate(java.security.cert.Certificate) TenantTraceSamplingHelper(org.eclipse.hono.tracing.TenantTraceSamplingHelper) DeviceCredentialsAuthProvider(org.eclipse.hono.adapter.auth.device.DeviceCredentialsAuthProvider) X509AuthProvider(org.eclipse.hono.adapter.auth.device.X509AuthProvider) ConnectionId(org.eclipse.californium.scandium.dtls.ConnectionId) CertificateVerificationResult(org.eclipse.californium.scandium.dtls.CertificateVerificationResult) Optional(java.util.Optional) AlertMessage(org.eclipse.californium.scandium.dtls.AlertMessage) Span(io.opentracing.Span) SubjectDnCredentials(org.eclipse.hono.adapter.auth.device.SubjectDnCredentials) Span(io.opentracing.Span) HandshakeException(org.eclipse.californium.scandium.dtls.HandshakeException) AlertMessage(org.eclipse.californium.scandium.dtls.AlertMessage) CertificateVerificationResult(org.eclipse.californium.scandium.dtls.CertificateVerificationResult)

Example 95 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class CoapContextTest method testStartAckTimerFallsBackToGlobalTimeout.

/**
 * Verifies that the global ACK timeout is used if no tenant specific value is configured.
 */
@Test
void testStartAckTimerFallsBackToGlobalTimeout() {
    final CoapExchange exchange = mock(CoapExchange.class);
    final Adapter coapConfig = new Adapter(Constants.PROTOCOL_ADAPTER_TYPE_COAP);
    final TenantObject tenant = TenantObject.from("tenant", true).addAdapter(coapConfig);
    final Device authenticatedDevice = new Device(tenant.getTenantId(), "device-id");
    final CoapContext ctx = CoapContext.fromRequest(exchange, authenticatedDevice, authenticatedDevice, "4711", span);
    ctx.startAcceptTimer(vertx, tenant, 500);
    verify(vertx).setTimer(eq(500L), VertxMockSupport.anyHandler());
}
Also used : TenantObject(org.eclipse.hono.util.TenantObject) Device(org.eclipse.hono.auth.Device) Adapter(org.eclipse.hono.util.Adapter) CoapExchange(org.eclipse.californium.core.server.resources.CoapExchange) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Aggregations

Device (org.eclipse.hono.auth.Device)115 HttpURLConnection (java.net.HttpURLConnection)74 Test (org.junit.jupiter.api.Test)72 Future (io.vertx.core.Future)69 ClientErrorException (org.eclipse.hono.client.ClientErrorException)67 Buffer (io.vertx.core.buffer.Buffer)66 Handler (io.vertx.core.Handler)63 TenantObject (org.eclipse.hono.util.TenantObject)63 Promise (io.vertx.core.Promise)59 Constants (org.eclipse.hono.util.Constants)58 Span (io.opentracing.Span)55 RegistrationAssertion (org.eclipse.hono.util.RegistrationAssertion)55 SpanContext (io.opentracing.SpanContext)53 VertxTestContext (io.vertx.junit5.VertxTestContext)52 VertxExtension (io.vertx.junit5.VertxExtension)51 MessageHelper (org.eclipse.hono.util.MessageHelper)51 ExtendWith (org.junit.jupiter.api.extension.ExtendWith)51 Mockito.when (org.mockito.Mockito.when)51 Truth.assertThat (com.google.common.truth.Truth.assertThat)50 ResourceIdentifier (org.eclipse.hono.util.ResourceIdentifier)47