TenantServiceBasedX509Authentication implements X509Authentication { @Override public Future<JsonObject> validateClientCertificate( final Certificate[] path, final SpanContext spanContext) { Objects.requireNonNull(path); final Span span = TracingHelper.buildChildSpan(tracer, spanContext, "verify 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<>(3); detail.put("subject DN", deviceCert.getSubjectX500Principal().getName()); detail.put("not before", deviceCert.getNotBefore().toString()); detail.put("not after", deviceCert.getNotAfter().toString()); span.log(detail); final Future<TenantObject> tenantTracker = getTenant(deviceCert, span); return tenantTracker .compose(tenant -> { final Set<TrustAnchor> trustAnchors = tenant.getTrustAnchors(); if (trustAnchors.isEmpty()) { log.debug("no valid trust anchors defined for tenant [{}]", tenant.getTenantId()); return Future.failedFuture(UNAUTHORIZED); } else { final List<X509Certificate> chainToValidate = Collections.singletonList(deviceCert); return certPathValidator.validate(chainToValidate, trustAnchors) .recover(t -> Future.failedFuture(UNAUTHORIZED)); } }).compose(ok -> getCredentials(x509chain, tenantTracker.result())); }).map(authInfo -> { span.log("certificate verified successfully"); span.finish(); return authInfo; }).recover(t -> { log.debug("verification of client certificate failed", t); TracingHelper.logError(span, t); span.finish(); return Future.failedFuture(t); }); } TenantServiceBasedX509Authentication(final TenantClientFactory tenantClientFactory);  TenantServiceBasedX509Authentication(
            final TenantClientFactory tenantClientFactory,
            final Tracer tracer);  TenantServiceBasedX509Authentication(
            final TenantClientFactory tenantClientFactory,
            final Tracer tracer,
            final DeviceCertificateValidator certPathValidator); @Override Future<JsonObject> validateClientCertificate(
            final Certificate[] path,
            final SpanContext spanContext);  }
@Test void testValidateClientCertificateContainsReadableCertificate() throws GeneralSecurityException { final TenantObject tenant = new TenantObject().addTrustAnchor(cert.getPublicKey(), cert.getSubjectX500Principal(), true); when(tenantClient.get(any(X500Principal.class), any())).thenReturn(Future.succeededFuture(tenant)); final Future<JsonObject> jsonObjectFuture = underTest.validateClientCertificate(certPath, null); assertTrue(jsonObjectFuture.succeeded()); assertArrayEquals(jsonObjectFuture.result().getBinary("client-certificate"), cert.getEncoded()); }
@Test void testValidateClientCertificateContainsNoCertificate() { final TenantObject tenant = new TenantObject().addTrustAnchor(cert.getPublicKey(), cert.getSubjectX500Principal(), false); when(tenantClient.get(any(X500Principal.class), any())).thenReturn(Future.succeededFuture(tenant)); final Future<JsonObject> jsonObjectFuture = underTest.validateClientCertificate(certPath, null); assertTrue(jsonObjectFuture.succeeded()); assertFalse(jsonObjectFuture.result().containsKey("client-certificate")); }