[feature] Make client IP logging configurable (#1799)

This commit is contained in:
Daenney 2023-05-21 17:12:47 +02:00 committed by GitHub
parent 68e54cbaa4
commit 107237c8e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 40 additions and 12 deletions

View File

@ -162,7 +162,7 @@
middlewares = append(middlewares, []gin.HandlerFunc{ middlewares = append(middlewares, []gin.HandlerFunc{
// note: hooks adding ctx fields must be ABOVE // note: hooks adding ctx fields must be ABOVE
// the logger, otherwise won't be accessible. // the logger, otherwise won't be accessible.
middleware.Logger(), middleware.Logger(config.GetLogClientIP()),
middleware.UserAgent(), middleware.UserAgent(),
middleware.CORS(), middleware.CORS(),
middleware.ExtraHeaders(), middleware.ExtraHeaders(),

View File

@ -107,7 +107,7 @@
middlewares = append(middlewares, tracing.InstrumentGin()) middlewares = append(middlewares, tracing.InstrumentGin())
} }
middlewares = append(middlewares, []gin.HandlerFunc{ middlewares = append(middlewares, []gin.HandlerFunc{
middleware.Logger(), middleware.Logger(config.GetLogClientIP()),
middleware.UserAgent(), middleware.UserAgent(),
middleware.CORS(), middleware.CORS(),
middleware.ExtraHeaders(), middleware.ExtraHeaders(),

View File

@ -30,6 +30,11 @@ log-level: "info"
# Default: false # Default: false
log-db-queries: false log-db-queries: false
# Bool. Include the client IP in the emitted log lines
# Options: [true, false]
# Default: true
log-client-ip: true
# String. Application name to use internally. # String. Application name to use internally.
# Examples: ["My Application","gotosocial"] # Examples: ["My Application","gotosocial"]
# Default: "gotosocial" # Default: "gotosocial"
@ -766,10 +771,6 @@ syslog-address: "localhost:514"
##### OBSERVABILITY SETTINGS ##### ##### OBSERVABILITY SETTINGS #####
################################## ##################################
# Bool. Enable generation/parsing of a request ID for each received HTTP Request.
# Default: true
request-id-enabled: true
# String. Header name to use to extract a request or trace ID from. Typically set by a # String. Header name to use to extract a request or trace ID from. Typically set by a
# loadbalancer or proxy. # loadbalancer or proxy.
# Default: "X-Request-Id" # Default: "X-Request-Id"

View File

@ -46,6 +46,7 @@ func fieldtag(field, tag string) string {
type Configuration struct { type Configuration struct {
LogLevel string `name:"log-level" usage:"Log level to run at: [trace, debug, info, warn, fatal]"` LogLevel string `name:"log-level" usage:"Log level to run at: [trace, debug, info, warn, fatal]"`
LogDbQueries bool `name:"log-db-queries" usage:"Log database queries verbosely when log-level is trace or debug"` LogDbQueries bool `name:"log-db-queries" usage:"Log database queries verbosely when log-level is trace or debug"`
LogClientIP bool `name:"log-client-ip" usage:"Include the client IP in logs"`
ApplicationName string `name:"application-name" usage:"Name of the application, used in various places internally"` ApplicationName string `name:"application-name" usage:"Name of the application, used in various places internally"`
LandingPageUser string `name:"landing-page-user" usage:"the user that should be shown on the instance's landing page"` LandingPageUser string `name:"landing-page-user" usage:"the user that should be shown on the instance's landing page"`
ConfigPath string `name:"config-path" usage:"Path to a file containing gotosocial configuration. Values set in this file will be overwritten by values set as env vars or arguments"` ConfigPath string `name:"config-path" usage:"Path to a file containing gotosocial configuration. Values set in this file will be overwritten by values set as env vars or arguments"`

View File

@ -198,4 +198,6 @@
AdminMediaPruneDryRun: true, AdminMediaPruneDryRun: true,
RequestIDHeader: "X-Request-Id", RequestIDHeader: "X-Request-Id",
LogClientIP: true,
} }

View File

@ -3679,3 +3679,28 @@ func GetRequestIDHeader() string { return global.GetRequestIDHeader() }
// SetRequestIDHeader safely sets the value for global configuration 'RequestIDHeader' field // SetRequestIDHeader safely sets the value for global configuration 'RequestIDHeader' field
func SetRequestIDHeader(v string) { global.SetRequestIDHeader(v) } func SetRequestIDHeader(v string) { global.SetRequestIDHeader(v) }
// GetLogClientIP safely fetches the Configuration value for state's 'LogClientIP' field
func (st *ConfigState) GetLogClientIP() (v bool) {
st.mutex.Lock()
v = st.config.LogClientIP
st.mutex.Unlock()
return
}
// SetLogClientIP safely sets the Configuration value for state's 'LogClientIP' field
func (st *ConfigState) SetLogClientIP(v bool) {
st.mutex.Lock()
defer st.mutex.Unlock()
st.config.LogClientIP = v
st.reloadToViper()
}
// LogClientIPFlag returns the flag name for the 'LogClientIP' field
func LogClientIPFlag() string { return "log-client-ip" }
// GetLogClientIP safely fetches the value for global configuration 'LogClientIP' field
func GetLogClientIP() bool { return global.GetLogClientIP() }
// SetLogClientIP safely sets the value for global configuration 'LogClientIP' field
func SetLogClientIP(v bool) { global.SetLogClientIP(v) }

View File

@ -34,7 +34,7 @@ func init() {
} }
return kvs return kvs
}) })
// Client IP middleware hook. // Public Key ID middleware hook.
log.Hook(func(ctx context.Context, kvs []kv.Field) []kv.Field { log.Hook(func(ctx context.Context, kvs []kv.Field) []kv.Field {
if id := PublicKeyID(ctx); id != "" { if id := PublicKeyID(ctx); id != "" {
return append(kvs, kv.Field{K: "pubKeyID", V: id}) return append(kvs, kv.Field{K: "pubKeyID", V: id})

View File

@ -31,7 +31,7 @@
) )
// Logger returns a gin middleware which provides request logging and panic recovery. // Logger returns a gin middleware which provides request logging and panic recovery.
func Logger() gin.HandlerFunc { func Logger(logClientIP bool) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
// Initialize the logging fields // Initialize the logging fields
fields := make(kv.Fields, 5, 7) fields := make(kv.Fields, 5, 7)
@ -72,10 +72,7 @@ func Logger() gin.HandlerFunc {
fields[2] = kv.Field{"method", c.Request.Method} fields[2] = kv.Field{"method", c.Request.Method}
fields[3] = kv.Field{"statusCode", code} fields[3] = kv.Field{"statusCode", code}
fields[4] = kv.Field{"path", path} fields[4] = kv.Field{"path", path}
if includeClientIP := true; includeClientIP { if logClientIP {
// TODO: make this configurable.
//
// Include clientIP if enabled.
fields = append(fields, kv.Field{ fields = append(fields, kv.Field{
"clientIP", c.ClientIP(), "clientIP", c.ClientIP(),
}) })

View File

@ -98,6 +98,7 @@ EXPECT=$(cat <<"EOF"
"letsencrypt-email-address": "", "letsencrypt-email-address": "",
"letsencrypt-enabled": true, "letsencrypt-enabled": true,
"letsencrypt-port": 80, "letsencrypt-port": 80,
"log-client-ip": false,
"log-db-queries": true, "log-db-queries": true,
"log-level": "info", "log-level": "info",
"media-description-max-chars": 5000, "media-description-max-chars": 5000,
@ -170,6 +171,7 @@ EOF
# ensure that these are parsed without panic # ensure that these are parsed without panic
OUTPUT=$(GTS_LOG_LEVEL='info' \ OUTPUT=$(GTS_LOG_LEVEL='info' \
GTS_LOG_DB_QUERIES=true \ GTS_LOG_DB_QUERIES=true \
GTS_LOG_CLIENT_IP=false \
GTS_APPLICATION_NAME=gts \ GTS_APPLICATION_NAME=gts \
GTS_LANDING_PAGE_USER=admin \ GTS_LANDING_PAGE_USER=admin \
GTS_HOST=example.com \ GTS_HOST=example.com \