use of io.opentracing.Tracer in project hono by eclipse.
the class TenantServiceBasedX509Authentication method validateClientCertificate.
/**
* Validates a certificate path using a trust anchor retrieved from
* the Tenant service.
* <p>
* This method uses the tenant client to determine the tenant that the client belongs to.
* <p>
* First, the {@link TenantClient#get(X500Principal, SpanContext)} method is invoked with the
* the issuer DN of the first element of the certificate path.
* <p>
* If that fails, then the {@link TenantClient#get(String, SpanContext)} method is invoked with
* the first label of the first requested host name.
*
* @param path The certificate path to validate.
* @param requestedHostNames The host names conveyed by the client in a TLS SNI extension.
* @param spanContext The <em>OpenTracing</em> context in which the
* validation should be executed, or {@code null}
* if no context exists (yet).
* @return A future indicating the outcome of the validation.
* <p>
* The future will be failed with a {@link org.eclipse.hono.client.ServiceInvocationException}
* if the certificate path could not be validated.
* <p>
* Otherwise, the future will be succeeded with a JSON object having
* the following properties:
* <pre>
* {
* "subject-dn": [RFC 2253 formatted subject DN of the client's end certificate],
* "tenant-id": [identifier of the tenant that the device belongs to]
* }
* </pre>
*
* If auto-provisioning is enabled for the trust anchor being used, the JSON object may optionally contain
* the DER encoding of the (validated) client certificate as a Base64 encoded byte array in the
* client-certificate property.
* @throws NullPointerException if certificate path is {@code null}.
*/
@Override
public Future<JsonObject> validateClientCertificate(final Certificate[] path, final List<String> requestedHostNames, final SpanContext spanContext) {
Objects.requireNonNull(path);
final Span span = TracingHelper.buildChildSpan(tracer, spanContext, "validate device certificate", getClass().getSimpleName()).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).start();
return getX509CertificatePath(path).compose(x509chain -> {
final X509Certificate deviceCert = x509chain.get(0);
final Map<String, String> detail = new HashMap<>(4);
detail.put("subject DN", deviceCert.getSubjectX500Principal().getName(X500Principal.RFC2253));
detail.put("issuer DN", deviceCert.getIssuerX500Principal().getName(X500Principal.RFC2253));
detail.put("not before", deviceCert.getNotBefore().toString());
detail.put("not after", deviceCert.getNotAfter().toString());
span.log(detail);
final Future<TenantObject> tenantTracker = getTenant(deviceCert, requestedHostNames, span);
return tenantTracker.compose(tenant -> {
final Set<TrustAnchor> trustAnchors = tenant.getTrustAnchors();
if (trustAnchors.isEmpty()) {
return Future.failedFuture(new ClientErrorException(tenant.getTenantId(), HttpURLConnection.HTTP_UNAUTHORIZED, "no valid trust anchors defined for tenant"));
} else {
if (log.isTraceEnabled()) {
final var b = new StringBuilder("found tenant [tenant-id: ").append(tenant.getTenantId()).append("]").append(" for client certificate [subject-dn: ").append(deviceCert.getSubjectX500Principal().getName(X500Principal.RFC2253)).append(", issuer-dn: ").append(deviceCert.getIssuerX500Principal().getName(X500Principal.RFC2253)).append("]").append(System.lineSeparator()).append("with trust anchors:").append(System.lineSeparator());
trustAnchors.stream().forEach(ta -> {
b.append("Trust Anchor [subject-dn: ").append(ta.getCAName()).append("]");
});
log.trace(b.toString());
}
final List<X509Certificate> chainToValidate = List.of(deviceCert);
return certPathValidator.validate(chainToValidate, trustAnchors).recover(t -> Future.failedFuture(new ClientErrorException(tenant.getTenantId(), HttpURLConnection.HTTP_UNAUTHORIZED, t.getMessage(), t)));
}
}).compose(ok -> getCredentials(x509chain, tenantTracker.result()));
}).onSuccess(authInfo -> span.log("certificate validated successfully")).onFailure(t -> {
log.debug("validation of client certificate failed", t);
TracingHelper.logError(span, t);
}).onComplete(ar -> span.finish());
}
use of io.opentracing.Tracer in project hono by eclipse.
the class AbstractProtocolAdapterApplication method prometheusResourceLimitChecks.
/**
* Creates resource limit checks based on data retrieved from a Prometheus server
* via its HTTP API.
*
* @param config The configuration properties.
* @param tenantClient The client to use for retrieving tenant configuration data.
* @throws NullPointerException if any of the parameters are {@code null}-
* @return The checks.
*/
protected ResourceLimitChecks prometheusResourceLimitChecks(final PrometheusBasedResourceLimitChecksConfig config, final TenantClient tenantClient) {
Objects.requireNonNull(config);
Objects.requireNonNull(tenantClient);
if (config.isHostConfigured()) {
final WebClientOptions webClientOptions = new WebClientOptions();
webClientOptions.setConnectTimeout(config.getConnectTimeout());
webClientOptions.setDefaultHost(config.getHost());
webClientOptions.setDefaultPort(config.getPort());
webClientOptions.setTrustOptions(config.getTrustOptions());
webClientOptions.setKeyCertOptions(config.getKeyCertOptions());
webClientOptions.setSsl(config.isTlsEnabled());
final var webClient = WebClient.create(vertx, webClientOptions);
final var cacheTimeout = Duration.ofSeconds(config.getCacheTimeout());
final Caffeine<Object, Object> builder = Caffeine.newBuilder().executor(Executors.newSingleThreadExecutor(r -> {
final var t = new Thread(r);
t.setDaemon(true);
return t;
})).initialCapacity(config.getCacheMinSize()).maximumSize(config.getCacheMaxSize()).expireAfterWrite(cacheTimeout).refreshAfterWrite(cacheTimeout.dividedBy(2));
return new PrometheusBasedResourceLimitChecks(builder.buildAsync(new ConnectedDevicesAsyncCacheLoader(webClient, config, tracer)), builder.buildAsync(new ConnectionDurationAsyncCacheLoader(webClient, config, tracer)), builder.buildAsync(new DataVolumeAsyncCacheLoader(webClient, config, tracer)), tenantClient, tracer);
} else {
return new NoopResourceLimitChecks();
}
}
use of io.opentracing.Tracer in project hono by eclipse.
the class LoraProtocolAdapterTest method setUp.
/**
* Sets up the fixture.
*/
@BeforeEach
public void setUp() {
vertx = mock(Vertx.class);
final Context context = VertxMockSupport.mockContext(vertx);
webClient = mock(WebClient.class);
this.properties = givenDefaultConfigurationProperties();
createClients();
prepareClients();
processMessageSpan = mock(Span.class);
when(processMessageSpan.context()).thenReturn(mock(SpanContext.class));
final Span otherSpan = mock(Span.class);
when(otherSpan.context()).thenReturn(mock(SpanContext.class));
final SpanBuilder processMessageSpanBuilder = mock(SpanBuilder.class, withSettings().defaultAnswer(RETURNS_SELF));
when(processMessageSpanBuilder.start()).thenReturn(processMessageSpan);
final SpanBuilder otherSpanBuilder = mock(SpanBuilder.class, withSettings().defaultAnswer(RETURNS_SELF));
when(otherSpanBuilder.start()).thenReturn(otherSpan);
final Tracer tracer = mock(Tracer.class);
when(tracer.buildSpan(eq(LoraProtocolAdapter.SPAN_NAME_PROCESS_MESSAGE))).thenReturn(processMessageSpanBuilder);
when(tracer.buildSpan(argThat(opName -> !opName.equals(LoraProtocolAdapter.SPAN_NAME_PROCESS_MESSAGE)))).thenReturn(otherSpanBuilder);
final HttpAdapterMetrics metrics = mock(HttpAdapterMetrics.class);
when(metrics.startTimer()).thenReturn(mock(Sample.class));
adapter = new LoraProtocolAdapter(webClient);
adapter.setConfig(properties);
adapter.setTracer(tracer);
adapter.init(vertx, context);
adapter.setMetrics(metrics);
setServiceClients(adapter);
}
use of io.opentracing.Tracer in project hono by eclipse.
the class AmqpAdapterClientSenderTestBase method setUp.
/**
* Sets up fixture.
*/
@BeforeEach
public void setUp() {
sender = AmqpClientUnitTestHelper.mockProtonSender();
protonDelivery = mock(ProtonDelivery.class);
when(protonDelivery.remotelySettled()).thenReturn(true);
final Accepted deliveryState = new Accepted();
when(protonDelivery.getRemoteState()).thenReturn(deliveryState);
when(sender.send(any(Message.class), VertxMockSupport.anyHandler())).thenReturn(protonDelivery);
final Span span = TracingMockSupport.mockSpan();
spanBuilder = TracingMockSupport.mockSpanBuilder(span);
final Tracer tracer = TracingMockSupport.mockTracer(spanBuilder);
connection = AmqpClientUnitTestHelper.mockHonoConnection(mock(Vertx.class));
when(connection.getTracer()).thenReturn(tracer);
when(connection.createSender(any(), any(), any())).thenReturn(Future.succeededFuture(sender));
}
use of io.opentracing.Tracer in project hono by eclipse.
the class CommandContext method createSpan.
/**
* Creates and starts an <em>OpenTracing</em> span for the command handling operation.
*
* @param tracer The tracer to use.
* @param command The command for which the span should be started.
* @param parentSpanContext The context of the span to reference as parent span.
* @param followsFromSpanContext A span context for which to add a <em>follows-from</em> reference,
* e.g. the span context for the operation to create the command consumer.
* @param componentName The component to set for the span.
* @return The created span.
* @throws NullPointerException if tracer or command is {@code null}.
*/
static Span createSpan(final Tracer tracer, final Command command, final SpanContext parentSpanContext, final SpanContext followsFromSpanContext, final String componentName) {
Objects.requireNonNull(tracer);
Objects.requireNonNull(command);
// we set the component tag to the class name because we have no access to
// the name of the enclosing component we are running in
final Tracer.SpanBuilder spanBuilder = TracingHelper.buildChildSpan(tracer, parentSpanContext, "handle command", componentName).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER).withTag(TracingHelper.TAG_TENANT_ID, command.getTenant()).withTag(TracingHelper.TAG_DEVICE_ID, command.getDeviceId());
if (command.getGatewayId() != null) {
spanBuilder.withTag(MessageHelper.APP_PROPERTY_GATEWAY_ID, command.getGatewayId());
}
spanBuilder.addReference(References.FOLLOWS_FROM, followsFromSpanContext);
final Span currentSpan = spanBuilder.start();
command.logToSpan(currentSpan);
return currentSpan;
}
Aggregations