summaryrefslogtreecommitdiffstats
path: root/jdisc_http_service
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2020-04-08 15:32:04 +0200
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2020-04-08 15:40:15 +0200
commit440de4cd80bf0640445ba854efc12942b2344b3a (patch)
treec435d38b3e4f75ed4b7c2b79940ca4cfafaae81c /jdisc_http_service
parent7ed8e0eda85d186d6a8250112a4a52a6a7cbc9ad (diff)
Report expired client certificate as a separate metric
Diffstat (limited to 'jdisc_http_service')
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java1
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailedListener.java4
-rw-r--r--jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java41
3 files changed, 46 insertions, 0 deletions
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
index c5f42ff9cc5..04db58f6d07 100644
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
+++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
@@ -110,6 +110,7 @@ public class JettyHttpServer extends AbstractServerProvider {
String CONTENT_SIZE = "jdisc.http.request.content_size";
String SSL_HANDSHAKE_FAILURE_MISSING_CLIENT_CERT = "jdisc.http.ssl.handshake.failure.missing_client_cert";
+ String SSL_HANDSHAKE_FAILURE_EXPIRED_CLIENT_CERT = "jdisc.http.ssl.handshake.failure.expired_client_cert";
String SSL_HANDSHAKE_FAILURE_INVALID_CLIENT_CERT = "jdisc.http.ssl.handshake.failure.invalid_client_cert";
String SSL_HANDSHAKE_FAILURE_INCOMPATIBLE_PROTOCOLS = "jdisc.http.ssl.handshake.failure.incompatible_protocols";
String SSL_HANDSHAKE_FAILURE_INCOMPATIBLE_CIPHERS = "jdisc.http.ssl.handshake.failure.incompatible_ciphers";
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailedListener.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailedListener.java
index 886071243ba..75df82036a2 100644
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailedListener.java
+++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailedListener.java
@@ -56,6 +56,10 @@ class SslHandshakeFailedListener implements SslHandshakeListener {
MISSING_CLIENT_CERT(
Metrics.SSL_HANDSHAKE_FAILURE_MISSING_CLIENT_CERT,
"Empty server certificate chain"),
+ EXPIRED_CLIENT_CERTIFICATE(
+ Metrics.SSL_HANDSHAKE_FAILURE_EXPIRED_CLIENT_CERT,
+ // Note: this pattern will match certificates with too late notBefore as well
+ "PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed"),
INVALID_CLIENT_CERT(
Metrics.SSL_HANDSHAKE_FAILURE_INVALID_CLIENT_CERT,
"PKIX path (building|validation) failed: .+");
diff --git a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java
index f2f3fb0ef11..dfa4fe37ef3 100644
--- a/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java
+++ b/jdisc_http_service/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java
@@ -27,6 +27,8 @@ import com.yahoo.jdisc.http.server.jetty.JettyHttpServer.Metrics;
import com.yahoo.jdisc.http.server.jetty.TestDrivers.TlsClientAuth;
import com.yahoo.jdisc.service.BindingSetNotFoundException;
import com.yahoo.security.KeyUtils;
+import com.yahoo.security.Pkcs10Csr;
+import com.yahoo.security.Pkcs10CsrBuilder;
import com.yahoo.security.SslContextBuilder;
import com.yahoo.security.X509CertificateBuilder;
import com.yahoo.security.X509CertificateUtils;
@@ -56,6 +58,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyPair;
+import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
@@ -667,6 +670,29 @@ public class HttpServerTest {
}
@Test
+ public void requireThatMetricIsIncrementedWhenClientUsesExpiredCertificateInHandshake() throws IOException {
+ Path rootPrivateKeyFile = tmpFolder.newFile().toPath();
+ Path rootCertificateFile = tmpFolder.newFile().toPath();
+ Path privateKeyFile = tmpFolder.newFile().toPath();
+ Path certificateFile = tmpFolder.newFile().toPath();
+ Instant notAfter = Instant.now().minus(100, ChronoUnit.DAYS);
+ generatePrivateKeyAndCertificate(rootPrivateKeyFile, rootCertificateFile, privateKeyFile, certificateFile, notAfter);
+ var metricConsumer = new MetricConsumerMock();
+ TestDriver driver = createSslTestDriver(rootCertificateFile, rootPrivateKeyFile, metricConsumer);
+
+ SSLContext clientCtx = new SslContextBuilder()
+ .withTrustStore(rootCertificateFile)
+ .withKeyStore(privateKeyFile, certificateFile)
+ .build();
+
+ assertHttpsRequestTriggersSslHandshakeException(
+ driver, clientCtx, null, null, "Received fatal alert: certificate_unknown");
+ verify(metricConsumer.mockitoMock())
+ .add(Metrics.SSL_HANDSHAKE_FAILURE_EXPIRED_CLIENT_CERT, 1L, MetricConsumerMock.STATIC_CONTEXT);
+ assertThat(driver.close(), is(true));
+ }
+
+ @Test
public void requireThatProxyProtocolIsAcceptedAndActualRemoteAddressStoredInAccessLog() throws Exception {
Path privateKeyFile = tmpFolder.newFile().toPath();
Path certificateFile = tmpFolder.newFile().toPath();
@@ -788,6 +814,21 @@ public class HttpServerTest {
Files.writeString(certificateFile, X509CertificateUtils.toPem(certificate));
}
+ private static void generatePrivateKeyAndCertificate(Path rootPrivateKeyFile, Path rootCertificateFile,
+ Path privateKeyFile, Path certificateFile, Instant notAfter) throws IOException {
+ generatePrivateKeyAndCertificate(rootPrivateKeyFile, rootCertificateFile);
+ X509Certificate rootCertificate = X509CertificateUtils.fromPem(Files.readString(rootCertificateFile));
+ PrivateKey privateKey = KeyUtils.fromPemEncodedPrivateKey(Files.readString(rootPrivateKeyFile));
+
+ KeyPair keyPair = KeyUtils.generateKeypair(RSA, 2048);
+ Files.writeString(privateKeyFile, KeyUtils.toPem(keyPair.getPrivate()));
+ Pkcs10Csr csr = Pkcs10CsrBuilder.fromKeypair(new X500Principal("CN=myclient"), keyPair, SHA256_WITH_RSA).build();
+ X509Certificate certificate = X509CertificateBuilder
+ .fromCsr(csr, rootCertificate.getSubjectX500Principal(), Instant.EPOCH, notAfter, privateKey, SHA256_WITH_RSA, BigInteger.ONE)
+ .build();
+ Files.writeString(certificateFile, X509CertificateUtils.toPem(certificate));
+ }
+
private static RequestHandler mockRequestHandler() {
final RequestHandler mockRequestHandler = mock(RequestHandler.class);
when(mockRequestHandler.refer()).thenReturn(References.NOOP_REFERENCE);