use of io.opentracing.Span in project hono by eclipse.
the class AbstractDeviceManagementService method createDevice.
@Override
public final Future<OperationResult<Id>> createDevice(final String tenantId, final Optional<String> deviceId, final Device device, final Span span) {
Objects.requireNonNull(tenantId);
Objects.requireNonNull(deviceId);
Objects.requireNonNull(device);
Objects.requireNonNull(span);
final String deviceIdValue = deviceId.orElseGet(() -> generateDeviceId(tenantId));
return this.tenantInformationService.tenantExists(tenantId, span).compose(result -> result.isError() ? Future.failedFuture(ServiceInvocationException.create(tenantId, result.getStatus(), "tenant does not exist", null)) : processCreateDevice(DeviceKey.from(result.getPayload(), deviceIdValue), device, span)).onSuccess(result -> NotificationEventBusSupport.sendNotification(vertx, new DeviceChangeNotification(LifecycleChange.CREATE, tenantId, deviceIdValue, Instant.now(), device.isEnabled()))).recover(t -> DeviceRegistryUtils.mapError(t, tenantId));
}
use of io.opentracing.Span in project hono by eclipse.
the class X509AuthHandlerTest method testParseCredentialsIncludesMqttClientId.
/**
* Verifies that the handler includes the MQTT client identifier in the authentication
* information retrieved from a device's CONNECT packet.
*
* @param ctx The vert.x test context.
* @throws SSLPeerUnverifiedException if the client certificate cannot be determined.
*/
@SuppressWarnings("unchecked")
@Test
public void testParseCredentialsIncludesMqttClientId(final VertxTestContext ctx) throws SSLPeerUnverifiedException {
// GIVEN an auth handler configured with an auth provider
final JsonObject authInfo = new JsonObject().put(RequestResponseApiConstants.FIELD_PAYLOAD_SUBJECT_DN, "CN=device").put(RequestResponseApiConstants.FIELD_PAYLOAD_TENANT_ID, "tenant");
when(clientAuth.validateClientCertificate(any(Certificate[].class), any(List.class), (SpanContext) any())).thenReturn(Future.succeededFuture(authInfo));
// WHEN trying to authenticate a request that contains a client certificate
final X509Certificate clientCert = getClientCertificate("CN=device", "CN=tenant");
final SSLSession sslSession = mock(SSLSession.class);
when(sslSession.getPeerCertificates()).thenReturn(new X509Certificate[] { clientCert });
final MqttEndpoint endpoint = mock(MqttEndpoint.class);
when(endpoint.isSsl()).thenReturn(true);
when(endpoint.sslSession()).thenReturn(sslSession);
when(endpoint.clientIdentifier()).thenReturn("mqtt-device");
final MqttConnectContext context = MqttConnectContext.fromConnectPacket(endpoint, span);
authHandler.parseCredentials(context).onComplete(ctx.succeeding(info -> {
ctx.verify(() -> {
assertThat(info.getString(RequestResponseApiConstants.FIELD_PAYLOAD_SUBJECT_DN)).isEqualTo("CN=device");
assertThat(info.getString(RequestResponseApiConstants.FIELD_PAYLOAD_TENANT_ID)).isEqualTo("tenant");
assertThat(info.getString(X509AuthHandler.PROPERTY_CLIENT_IDENTIFIER)).isEqualTo("mqtt-device");
});
ctx.completeNow();
}));
}
use of io.opentracing.Span in project hono by eclipse.
the class HttpBasedMessageMappingTest method testMapMessageSucceeds.
/**
* Verifies that the result returned by the mapping service contains the
* mapped payload, device ID and additional properties.
*
* @param ctx The helper to use for running tests on vert.x.
*/
@SuppressWarnings("unchecked")
@Test
public void testMapMessageSucceeds(final VertxTestContext ctx) {
config.setMapperEndpoints(Map.of("mapper", MapperEndpoint.from("host", 1234, "/uri", false)));
final ResourceIdentifier targetAddress = ResourceIdentifier.from(TelemetryConstants.TELEMETRY_ENDPOINT, TEST_TENANT_ID, "gateway");
final String newDeviceId = "new-device";
final HttpRequest<Buffer> httpRequest = mock(HttpRequest.class, withSettings().defaultAnswer(RETURNS_SELF));
final MultiMap responseHeaders = MultiMap.caseInsensitiveMultiMap();
responseHeaders.add(MessageHelper.APP_PROPERTY_DEVICE_ID, newDeviceId);
responseHeaders.add("foo", "bar");
final Buffer responseBody = Buffer.buffer("changed");
final HttpResponse<Buffer> httpResponse = mock(HttpResponse.class);
when(httpResponse.headers()).thenReturn(responseHeaders);
when(httpResponse.bodyAsBuffer()).thenReturn(responseBody);
when(httpResponse.statusCode()).thenReturn(HttpURLConnection.HTTP_OK);
when(mapperWebClient.post(anyInt(), anyString(), anyString())).thenReturn(httpRequest);
final String topic = String.format("%s/?content-type=%s", TelemetryConstants.TELEMETRY_ENDPOINT, URLEncoder.encode("text/plain", StandardCharsets.UTF_8));
final MqttPublishMessage message = newMessage(MqttQoS.AT_LEAST_ONCE, topic);
final MqttContext context = newContext(message, span, new Device(TEST_TENANT_ID, "gateway"));
final RegistrationAssertion assertion = new RegistrationAssertion("gateway").setDownstreamMessageMapper("mapper");
messageMapping.mapDownstreamMessage(context, targetAddress, assertion).onComplete(ctx.succeeding(mappedMessage -> {
ctx.verify(() -> {
assertThat(mappedMessage.getTargetAddress().getResourceId()).isEqualTo("new-device");
assertThat(mappedMessage.getPayload()).isEqualTo(responseBody);
assertThat(mappedMessage.getAdditionalProperties()).doesNotContainKey(MessageHelper.APP_PROPERTY_DEVICE_ID);
assertThat(mappedMessage.getAdditionalProperties()).containsEntry("foo", "bar");
});
ctx.completeNow();
}));
final ArgumentCaptor<Handler<AsyncResult<HttpResponse<Buffer>>>> handleCaptor = VertxMockSupport.argumentCaptorHandler();
verify(httpRequest).sendBuffer(any(Buffer.class), handleCaptor.capture());
handleCaptor.getValue().handle(Future.succeededFuture(httpResponse));
final ArgumentCaptor<MultiMap> headersCaptor = ArgumentCaptor.forClass(MultiMap.class);
verify(httpRequest).putHeaders(headersCaptor.capture());
final MultiMap addedHeaders = headersCaptor.getValue();
assertThat(addedHeaders.contains(MessageHelper.APP_PROPERTY_ORIG_ADDRESS, topic, false)).isTrue();
assertThat(addedHeaders.contains(HttpHeaders.CONTENT_TYPE.toString(), "text/plain", false));
}
use of io.opentracing.Span in project hono by eclipse.
the class HttpBasedMessageMappingTest method testMappingFailsForWhenPayloadCannotMapped.
/**
* Verifies that the downstream mapper returns a failed future with a ServerErrorException if the downstream mapper has been configured
* for an adapter but the remote service returns a 403 status code indicating that the device payload cannot be mapped.
*
* @param ctx The Vert.x test context.
*/
@Test
@SuppressWarnings("unchecked")
public void testMappingFailsForWhenPayloadCannotMapped(final VertxTestContext ctx) {
config.setMapperEndpoints(Map.of("mapper", MapperEndpoint.from("host", 1234, "/uri", false)));
final ResourceIdentifier targetAddress = ResourceIdentifier.from(TelemetryConstants.TELEMETRY_ENDPOINT, TEST_TENANT_ID, "gateway");
final HttpRequest<Buffer> httpRequest = mock(HttpRequest.class, withSettings().defaultAnswer(RETURNS_SELF));
final HttpResponse<Buffer> httpResponse = mock(HttpResponse.class);
when(httpResponse.statusCode()).thenReturn(HttpURLConnection.HTTP_FORBIDDEN);
when(mapperWebClient.post(anyInt(), anyString(), anyString())).thenReturn(httpRequest);
final MqttPublishMessage message = newMessage(MqttQoS.AT_LEAST_ONCE, "mqtt-topic");
final MqttContext context = newContext(message, span, new Device(TEST_TENANT_ID, "gateway"));
final RegistrationAssertion assertion = new RegistrationAssertion("gateway").setDownstreamMessageMapper("mapper");
messageMapping.mapDownstreamMessage(context, targetAddress, assertion).onComplete(ctx.failing(t -> {
ctx.verify(() -> {
assertThat(t).isInstanceOf(ServerErrorException.class);
assertThat((((ServerErrorException) t).getErrorCode())).isEqualTo(HttpURLConnection.HTTP_UNAVAILABLE);
});
ctx.completeNow();
}));
final ArgumentCaptor<Handler<AsyncResult<HttpResponse<Buffer>>>> handlerCaptor = VertxMockSupport.argumentCaptorHandler();
verify(httpRequest).sendBuffer(any(Buffer.class), handlerCaptor.capture());
handlerCaptor.getValue().handle(Future.succeededFuture(httpResponse));
}
use of io.opentracing.Span in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method testMessageLimitExceededForACommandResponseMessage.
/**
* Verifies that a command response message is rejected due to the limit exceeded.
*
* @param ctx The vert.x test context.
*/
@Test
public void testMessageLimitExceededForACommandResponseMessage(final VertxTestContext ctx) {
// GIVEN an adapter
givenAnAdapter(properties);
final CommandResponseSender sender = givenACommandResponseSenderForAnyTenant();
// WHEN the message limit exceeds
when(resourceLimitChecks.isMessageLimitReached(any(TenantObject.class), anyLong(), any(SpanContext.class))).thenReturn(Future.succeededFuture(Boolean.TRUE));
// WHEN a device of "tenant" publishes a command response message
final MqttPublishMessage msg = mock(MqttPublishMessage.class);
when(msg.topicName()).thenReturn("e/tenant/device");
when(msg.qosLevel()).thenReturn(MqttQoS.AT_MOST_ONCE);
when(msg.payload()).thenReturn(Buffer.buffer("test"));
adapter.uploadMessage(newMqttContext(msg, mockEndpoint(), span), ResourceIdentifier.fromString(String.format("%s/tenant/device/res/%s/200", getCommandEndpoint(), Commands.encodeRequestIdParameters("cmd123", "to", "deviceId", MessagingType.amqp))), msg).onComplete(ctx.failing(t -> {
ctx.verify(() -> {
// THEN the request fails with a 429 error
assertThat(((ClientErrorException) t).getErrorCode()).isEqualTo(HttpUtils.HTTP_TOO_MANY_REQUESTS);
// AND the response is not being forwarded
verify(sender, never()).sendCommandResponse(any(TenantObject.class), any(RegistrationAssertion.class), any(CommandResponse.class), (SpanContext) any());
// AND has reported the message as unprocessable
verify(metrics).reportCommand(eq(MetricsTags.Direction.RESPONSE), eq("tenant"), any(), eq(MetricsTags.ProcessingOutcome.UNPROCESSABLE), anyInt(), any());
});
ctx.completeNow();
}));
}
Aggregations