From 27c02b5a56449d232c4c18418cb5e91052d8363f Mon Sep 17 00:00:00 2001 From: xmessi <112385449+xmessi@users.noreply.github.com> Date: Mon, 21 Nov 2022 10:18:05 +0100 Subject: [PATCH] Log TLS client subject --- docs/content/observability/access-logs.md | 1 + pkg/middlewares/accesslog/logdata.go | 3 +++ pkg/middlewares/accesslog/logger.go | 3 +++ pkg/middlewares/accesslog/logger_test.go | 6 ++++++ 4 files changed, 13 insertions(+) diff --git a/docs/content/observability/access-logs.md b/docs/content/observability/access-logs.md index a7739a12f..98fca36ef 100644 --- a/docs/content/observability/access-logs.md +++ b/docs/content/observability/access-logs.md @@ -229,6 +229,7 @@ accessLog: | `RetryAttempts` | The amount of attempts the request was retried. | | `TLSVersion` | The TLS version used by the connection (e.g. `1.2`) (if connection is TLS). | | `TLSCipher` | The TLS cipher used by the connection (e.g. `TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA`) (if connection is TLS) | + | `TLSClientSubject` | The string representation of the TLS client certificate's Subject (e.g. `CN=username,O=organization`) | ## Log Rotation diff --git a/pkg/middlewares/accesslog/logdata.go b/pkg/middlewares/accesslog/logdata.go index 1db168446..ef3f3be6c 100644 --- a/pkg/middlewares/accesslog/logdata.go +++ b/pkg/middlewares/accesslog/logdata.go @@ -75,6 +75,8 @@ const ( TLSVersion = "TLSVersion" // TLSCipher is the cipher used in the request. TLSCipher = "TLSCipher" + // TLSClientSubject is the string representation of the TLS client certificate's Subject. + TLSClientSubject = "TLSClientSubject" ) // These are written out in the default case when no config is provided to specify keys of interest. @@ -118,6 +120,7 @@ func init() { allCoreKeys[RetryAttempts] = struct{}{} allCoreKeys[TLSVersion] = struct{}{} allCoreKeys[TLSCipher] = struct{}{} + allCoreKeys[TLSClientSubject] = struct{}{} } // CoreLogData holds the fields computed from the request/response. diff --git a/pkg/middlewares/accesslog/logger.go b/pkg/middlewares/accesslog/logger.go index cf729c6de..e5ade7b48 100644 --- a/pkg/middlewares/accesslog/logger.go +++ b/pkg/middlewares/accesslog/logger.go @@ -218,6 +218,9 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http core[RequestScheme] = "https" core[TLSVersion] = traefiktls.GetVersion(req.TLS) core[TLSCipher] = traefiktls.GetCipherName(req.TLS) + if len(req.TLS.PeerCertificates) > 0 && req.TLS.PeerCertificates[0] != nil { + core[TLSClientSubject] = req.TLS.PeerCertificates[0].Subject.String() + } } core[ClientAddr] = req.RemoteAddr diff --git a/pkg/middlewares/accesslog/logger_test.go b/pkg/middlewares/accesslog/logger_test.go index 80bda1530..967070b7d 100644 --- a/pkg/middlewares/accesslog/logger_test.go +++ b/pkg/middlewares/accesslog/logger_test.go @@ -3,6 +3,8 @@ package accesslog import ( "bytes" "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" "encoding/json" "fmt" "io" @@ -370,6 +372,7 @@ func TestLoggerJSON(t *testing.T) { Duration: assertFloat64NotZero(), Overhead: assertFloat64NotZero(), RetryAttempts: assertFloat64(float64(testRetryAttempts)), + TLSClientSubject: assertString("CN=foobar"), TLSVersion: assertString("1.3"), TLSCipher: assertString("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"), "time": assertNotEmpty(), @@ -780,6 +783,9 @@ func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) { req.TLS = &tls.ConnectionState{ Version: tls.VersionTLS13, CipherSuite: tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + PeerCertificates: []*x509.Certificate{{ + Subject: pkix.Name{CommonName: "foobar"}, + }}, } }