From 2599d7ee75dd98c84e5f6ac88d35f2546812d3fe Mon Sep 17 00:00:00 2001 From: Ramon de Klein Date: Mon, 13 Jan 2025 15:10:25 +0100 Subject: [PATCH] Enable verbose Vault request logging --- internal/http/log.go | 46 +++++++++++++++++++++++++++++++ internal/keystore/vault/config.go | 3 ++ internal/keystore/vault/vault.go | 4 +++ kesconf/config.go | 3 ++ kesconf/file.go | 4 +++ 5 files changed, 60 insertions(+) create mode 100644 internal/http/log.go diff --git a/internal/http/log.go b/internal/http/log.go new file mode 100644 index 00000000..55b19d02 --- /dev/null +++ b/internal/http/log.go @@ -0,0 +1,46 @@ +package http + +import ( + "log/slog" + "net/http" + "time" +) + +// LoggingTransport is an http.RoundTripper that logs the request and response. +type LoggingTransport struct { + http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. +func (lt *LoggingTransport) RoundTrip(req *http.Request) (*http.Response, error) { + rt := lt.RoundTripper + if rt == nil { + rt = http.DefaultTransport + } + + start := time.Now() + + resp, err := rt.RoundTrip(req) + switch { + case err != nil: + slog.Info("HTTP error", + slog.String("method", req.Method), + slog.String("url", req.URL.String()), + slog.Duration("duration", time.Since(start)), + slog.String("error", err.Error())) + case resp.StatusCode < 300: + slog.Info("HTTP error response", + slog.String("method", req.Method), + slog.String("url", req.URL.String()), + slog.Duration("duration", time.Since(start)), + slog.String("status", resp.Status)) + default: + slog.Debug("HTTP success response", + slog.String("method", req.Method), + slog.String("url", req.URL.String()), + slog.Duration("duration", time.Since(start)), + slog.String("status", resp.Status)) + } + + return resp, err +} diff --git a/internal/keystore/vault/config.go b/internal/keystore/vault/config.go index c9c34904..9d85126d 100644 --- a/internal/keystore/vault/config.go +++ b/internal/keystore/vault/config.go @@ -220,6 +220,9 @@ type Config struct { // host's root CA set is used. CAPath string + // Flag to enable logging of all Vault HTTP requests + Verbose bool + lock sync.RWMutex } diff --git a/internal/keystore/vault/vault.go b/internal/keystore/vault/vault.go index 81483b50..1f226189 100644 --- a/internal/keystore/vault/vault.go +++ b/internal/keystore/vault/vault.go @@ -26,6 +26,7 @@ import ( "aead.dev/mem" vaultapi "github.com/hashicorp/vault/api" "github.com/minio/kes" + internalhttp "github.com/minio/kes/internal/http" "github.com/minio/kes/internal/keystore" kesdk "github.com/minio/kms-go/kes" ) @@ -112,6 +113,9 @@ func Connect(ctx context.Context, c *Config) (*Store, error) { tr.DisableKeepAlives = true tr.MaxIdleConnsPerHost = -1 } + if c.Verbose { + config.HttpClient.Transport = &internalhttp.LoggingTransport{RoundTripper: config.HttpClient.Transport} + } vaultClient, err := vaultapi.NewClient(config) if err != nil { return nil, err diff --git a/kesconf/config.go b/kesconf/config.go index 67860da2..3234c0b9 100644 --- a/kesconf/config.go +++ b/kesconf/config.go @@ -121,6 +121,8 @@ type ymlFile struct { Status struct { Ping env[time.Duration] `yaml:"ping"` } `yaml:"status"` + + Verbose bool `yaml:"verbose"` } `yaml:"vault"` Fortanix *struct { @@ -476,6 +478,7 @@ func ymlToKeyStore(y *ymlFile) (KeyStore, error) { Certificate: y.KeyStore.Vault.TLS.Certificate.Value, CAPath: y.KeyStore.Vault.TLS.CAPath.Value, StatusPing: y.KeyStore.Vault.Status.Ping.Value, + Verbose: y.KeyStore.Vault.Verbose.Value, } if y.KeyStore.Vault.AppRole != nil { s.AppRole = &VaultAppRoleAuth{ diff --git a/kesconf/file.go b/kesconf/file.go index c60218d6..89a429f1 100644 --- a/kesconf/file.go +++ b/kesconf/file.go @@ -455,6 +455,9 @@ type VaultKeyStore struct { // is checked. // If not set, defaults to 10s. StatusPing time.Duration + + // Verbose enables logging of all HTTP requests to Vault + Verbose bool } // VaultAppRoleAuth is a structure containing the configuration @@ -545,6 +548,7 @@ func (s *VaultKeyStore) Connect(ctx context.Context) (kes.KeyStore, error) { Certificate: s.Certificate, CAPath: s.CAPath, StatusPingAfter: s.StatusPing, + Verbose: s.Verbose, } if s.AppRole != nil { c.AppRole = &vault.AppRole{