Skip to content

Commit

Permalink
logging: add replace filter for static value replacement
Browse files Browse the repository at this point in the history
This filter is intended to be useful in scenarios where you may want to
redact a value with a static string, giving you information that the
field did previously exist and was present, but not revealing the value
itself in the logs.

This was inspired by work on adding more complete support for removing
sensitive values from logs [1]. An example use case would be the
Authorization header in request log output, for which the value should
usually not be logged, but it may be quite useful for debugging to
confirm that the header was present in the request.

[1] caddyserver#3958
  • Loading branch information
kujenga committed Feb 9, 2021
1 parent 653a0d3 commit 0ceada5
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
7 changes: 4 additions & 3 deletions caddytest/integration/caddyfile_adapt/log_filters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ log {
format filter {
wrap console
fields {
request>headers>Authorization delete
request>headers>Authorization replace REDACTED
request>headers>Server delete
request>remote_addr ip_mask {
ipv4 24
Expand All @@ -30,7 +30,8 @@ log {
"encoder": {
"fields": {
"request\u003eheaders\u003eAuthorization": {
"filter": "delete"
"filter": "replace",
"value": "REDACTED"
},
"request\u003eheaders\u003eServer": {
"filter": "delete"
Expand Down Expand Up @@ -66,4 +67,4 @@ log {
}
}
}
}
}
32 changes: 32 additions & 0 deletions modules/logging/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

func init() {
caddy.RegisterModule(DeleteFilter{})
caddy.RegisterModule(ReplaceFilter{})
caddy.RegisterModule(IPMaskFilter{})
}

Expand Down Expand Up @@ -57,6 +58,37 @@ func (DeleteFilter) Filter(in zapcore.Field) zapcore.Field {
return in
}

// ReplaceFilter is a Caddy log field filter that
// replaces the field with the indicated string.
type ReplaceFilter struct {
Value string `json:"value,omitempty"`
}

// CaddyModule returns the Caddy module information.
func (ReplaceFilter) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "caddy.logging.encoders.filter.replace",
New: func() caddy.Module { return new(ReplaceFilter) },
}
}

// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (f *ReplaceFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
if d.NextArg() {
f.Value = d.Val()
}
}
return nil
}

// Filter filters the input field with the replacement value.
func (f *ReplaceFilter) Filter(in zapcore.Field) zapcore.Field {
in.Type = zapcore.StringType
in.String = f.Value
return in
}

// IPMaskFilter is a Caddy log field filter that
// masks IP addresses.
type IPMaskFilter struct {
Expand Down

0 comments on commit 0ceada5

Please sign in to comment.