aboutsummaryrefslogtreecommitdiffstats
path: root/container-core
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2022-01-27 16:20:19 +0100
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2022-01-27 16:20:19 +0100
commit2f1e67ec08a409f074b7f59975cb33ab6b9cf612 (patch)
treef5c0823ad857fa4b824159e1bdcbd18fb8ef9f73 /container-core
parentba53a6b811628860306a9cbea0dce275c46875b1 (diff)
Add issuer and fingerprint of peer certificate to connection log
Diffstat (limited to 'container-core')
-rw-r--r--container-core/src/main/java/com/yahoo/container/logging/ConnectionLogEntry.java16
-rw-r--r--container-core/src/main/java/com/yahoo/container/logging/JsonConnectionLogWriter.java6
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java26
3 files changed, 42 insertions, 6 deletions
diff --git a/container-core/src/main/java/com/yahoo/container/logging/ConnectionLogEntry.java b/container-core/src/main/java/com/yahoo/container/logging/ConnectionLogEntry.java
index 26cdd1597c5..e2eeb5d3517 100644
--- a/container-core/src/main/java/com/yahoo/container/logging/ConnectionLogEntry.java
+++ b/container-core/src/main/java/com/yahoo/container/logging/ConnectionLogEntry.java
@@ -31,6 +31,8 @@ public class ConnectionLogEntry {
private final String sslPeerSubject;
private final Instant sslPeerNotBefore;
private final Instant sslPeerNotAfter;
+ private final String sslPeerIssuerSubject;
+ private final String sslPeerFingerprint;
private final String sslSniServerName;
private final SslHandshakeFailure sslHandshakeFailure;
private final List<String> sslSubjectAlternativeNames;
@@ -58,6 +60,8 @@ public class ConnectionLogEntry {
this.sslPeerSubject = builder.sslPeerSubject;
this.sslPeerNotBefore = builder.sslPeerNotBefore;
this.sslPeerNotAfter = builder.sslPeerNotAfter;
+ this.sslPeerIssuerSubject = builder.sslPeerIssuerSubject;
+ this.sslPeerFingerprint = builder.sslPeerFingerprint;
this.sslSniServerName = builder.sslSniServerName;
this.sslHandshakeFailure = builder.sslHandshakeFailure;
this.sslSubjectAlternativeNames = builder.sslSubjectAlternativeNames;
@@ -88,6 +92,8 @@ public class ConnectionLogEntry {
public Optional<String> sslPeerSubject() { return Optional.ofNullable(sslPeerSubject); }
public Optional<Instant> sslPeerNotBefore() { return Optional.ofNullable(sslPeerNotBefore); }
public Optional<Instant> sslPeerNotAfter() { return Optional.ofNullable(sslPeerNotAfter); }
+ public Optional<String> sslPeerIssuerSubject() { return Optional.ofNullable(sslPeerIssuerSubject); }
+ public Optional<String> sslPeerFingerprint() { return Optional.ofNullable(sslPeerFingerprint); }
public Optional<String> sslSniServerName() { return Optional.ofNullable(sslSniServerName); }
public Optional<SslHandshakeFailure> sslHandshakeFailure() { return Optional.ofNullable(sslHandshakeFailure); }
public List<String> sslSubjectAlternativeNames() { return sslSubjectAlternativeNames == null ? List.of() : sslSubjectAlternativeNames; }
@@ -140,6 +146,8 @@ public class ConnectionLogEntry {
private String sslPeerSubject;
private Instant sslPeerNotBefore;
private Instant sslPeerNotAfter;
+ private String sslPeerIssuerSubject;
+ private String sslPeerFingerprint;
private String sslSniServerName;
private SslHandshakeFailure sslHandshakeFailure;
private List<String> sslSubjectAlternativeNames;
@@ -221,6 +229,14 @@ public class ConnectionLogEntry {
this.sslPeerNotAfter = sslPeerNotAfter;
return this;
}
+ public Builder withSslPeerIssuerSubject(String value) {
+ this.sslPeerIssuerSubject = value;
+ return this;
+ }
+ public Builder withSslPeerFingerprint(String value) {
+ this.sslPeerFingerprint = value;
+ return this;
+ }
public Builder withSslSniServerName(String sslSniServerName) {
this.sslSniServerName = sslSniServerName;
return this;
diff --git a/container-core/src/main/java/com/yahoo/container/logging/JsonConnectionLogWriter.java b/container-core/src/main/java/com/yahoo/container/logging/JsonConnectionLogWriter.java
index d686c97249f..6d98c247ca0 100644
--- a/container-core/src/main/java/com/yahoo/container/logging/JsonConnectionLogWriter.java
+++ b/container-core/src/main/java/com/yahoo/container/logging/JsonConnectionLogWriter.java
@@ -68,20 +68,24 @@ class JsonConnectionLogWriter implements LogWriter<ConnectionLogEntry> {
Instant sslPeerNotBefore = unwrap(record.sslPeerNotBefore());
Instant sslPeerNotAfter = unwrap(record.sslPeerNotAfter());
String sslSniServerName = unwrap(record.sslSniServerName());
+ String sslPeerIssuerSubject = unwrap(record.sslPeerIssuerSubject());
+ String sslPeerFingerprint = unwrap(record.sslPeerFingerprint());
ConnectionLogEntry.SslHandshakeFailure sslHandshakeFailure = unwrap(record.sslHandshakeFailure());
List<String> sslSubjectAlternativeNames = record.sslSubjectAlternativeNames();
if (isAnyValuePresent(
sslProtocol, sslSessionId, sslCipherSuite, sslPeerSubject, sslPeerNotBefore, sslPeerNotAfter,
- sslSniServerName, sslHandshakeFailure)) {
+ sslSniServerName, sslHandshakeFailure, sslPeerIssuerSubject, sslPeerFingerprint)) {
generator.writeObjectFieldStart("ssl");
writeOptionalString(generator, "protocol", sslProtocol);
writeOptionalString(generator, "sessionId", sslSessionId);
writeOptionalString(generator, "cipherSuite", sslCipherSuite);
writeOptionalString(generator, "peerSubject", sslPeerSubject);
+ writeOptionalString(generator, "peerIssuerSubject", sslPeerIssuerSubject);
writeOptionalTimestamp(generator, "peerNotBefore", sslPeerNotBefore);
writeOptionalTimestamp(generator, "peerNotAfter", sslPeerNotAfter);
+ writeOptionalString(generator, "peerFingerprint", sslPeerFingerprint);
writeOptionalString(generator, "sniServerName", sslSniServerName);
if (sslHandshakeFailure != null) {
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java
index 451a7dbf10d..4e3fd3f29b3 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java
@@ -30,6 +30,9 @@ import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.StandardConstants;
import java.net.InetSocketAddress;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.util.ArrayList;
@@ -227,7 +230,6 @@ class JettyConnectionLogger extends AbstractLifeCycle implements Connection.List
throw new IllegalArgumentException("Unknown connection endpoint type: " + endpoint.getClass().getName());
}
}
-
@FunctionalInterface private interface ListenerHandler { void run() throws Exception; }
private static class ConnectionInfo {
@@ -249,6 +251,8 @@ class JettyConnectionLogger extends AbstractLifeCycle implements Connection.List
private Date sslPeerNotBefore;
private Date sslPeerNotAfter;
private List<SNIServerName> sslSniServerNames;
+ private String sslPeerIssuerSubject;
+ private byte[] sslPeerEncodedCertificate;
private SSLHandshakeException sslHandshakeException;
private List<String> sslSubjectAlternativeNames;
private String proxyProtocolVersion;
@@ -307,8 +311,9 @@ class JettyConnectionLogger extends AbstractLifeCycle implements Connection.List
this.sslSubjectAlternativeNames = X509CertificateUtils.getSubjectAlternativeNames(peerCertificate).stream()
.map(SubjectAlternativeName::getValue)
.collect(Collectors.toList());
-
- } catch (SSLPeerUnverifiedException e) {
+ this.sslPeerIssuerSubject = peerCertificate.getIssuerDN().getName();
+ this.sslPeerEncodedCertificate = peerCertificate.getEncoded();
+ } catch (SSLPeerUnverifiedException | CertificateEncodingException e) {
// Throw if peer is not authenticated (e.g when client auth is disabled)
// JSSE provides no means of checking for client authentication without catching this exception
}
@@ -365,10 +370,13 @@ class JettyConnectionLogger extends AbstractLifeCycle implements Connection.List
.findAny()
.ifPresent(builder::withSslSniServerName);
}
- if (sslPeerSubject != null && sslPeerNotAfter != null && sslPeerNotBefore != null) {
+ if (sslPeerSubject != null && sslPeerNotAfter != null && sslPeerNotBefore != null
+ && sslPeerIssuerSubject != null && sslPeerEncodedCertificate != null) {
builder.withSslPeerSubject(sslPeerSubject)
+ .withSslPeerIssuerSubject(sslPeerIssuerSubject)
.withSslPeerNotAfter(sslPeerNotAfter.toInstant())
- .withSslPeerNotBefore(sslPeerNotBefore.toInstant());
+ .withSslPeerNotBefore(sslPeerNotBefore.toInstant())
+ .withSslPeerFingerprint(certificateFingerprint(sslPeerEncodedCertificate));
}
if (sslSubjectAlternativeNames != null && !sslSubjectAlternativeNames.isEmpty()) {
builder.withSslSubjectAlternativeNames(sslSubjectAlternativeNames);
@@ -394,6 +402,14 @@ class JettyConnectionLogger extends AbstractLifeCycle implements Connection.List
return builder.build();
}
+ private static String certificateFingerprint(byte[] derEncoded) {
+ try {
+ return HexDump.toHexString(MessageDigest.getInstance("SHA-1").digest(derEncoded));
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
}
}