Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/m-mizutani/masq
A utility to redact sensitive data for slog in Go
https://github.com/m-mizutani/masq
Last synced: 6 days ago
JSON representation
A utility to redact sensitive data for slog in Go
- Host: GitHub
- URL: https://github.com/m-mizutani/masq
- Owner: m-mizutani
- License: apache-2.0
- Created: 2022-12-25T08:05:37.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-12-09T01:50:48.000Z (about 1 month ago)
- Last Synced: 2024-12-30T11:59:18.518Z (14 days ago)
- Language: Go
- Homepage:
- Size: 65.4 KB
- Stars: 110
- Watchers: 3
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-slog - masq
README
# masq: redacting sensitive data in slog [![Go Reference](https://pkg.go.dev/badge/github.com/m-mizutani/masq.svg)](https://pkg.go.dev/github.com/m-mizutani/masq) [![test](https://github.com/m-mizutani/masq/actions/workflows/test.yml/badge.svg)](https://github.com/m-mizutani/masq/actions/workflows/test.yml) [![gosec](https://github.com/m-mizutani/masq/actions/workflows/gosec.yml/badge.svg)](https://github.com/m-mizutani/masq/actions/workflows/gosec.yml) [![trivy](https://github.com/m-mizutani/masq/actions/workflows/trivy.yml/badge.svg)](https://github.com/m-mizutani/masq/actions/workflows/trivy.yml)
`masq` is a redacting utility to conceal sensitive data for [slog](https://pkg.go.dev/golang.org/x/exp/slog) that is official Go structured logging library. The concealing feature reduce risk to store secret values (API token, password and such things) and sensitive data like PII (Personal Identifiable Information) such as address, phone number, email address and etc into logging storage.
```go
u := struct {
ID string
Email EmailAddr
}{
ID: "u123",
Email: "[email protected]",
}logger := slog.New(
slog.NewJSONHandler(
os.Stdout,
&slog.HandlerOptions{
ReplaceAttr: masq.New(masq.WithType[EmailAddr]()),
},
),
)logger.Info("hello", slog.Any("user", u))
```Then, output is following (jq formatted).
```json
{
"time": "2022-12-25T09:00:00.123456789",
"level": "INFO",
"msg": "hello",
"user": {
"ID": "u123",
"Email": "[FILTERED]" // <- Concealed
}
}
```## Usage
`masq.New()` provides a function for `ReplaceAttr` of `slog.HandlerOptions`. `masq.New` can specify one or multiple `masq.Option` to identify value and field to be concealed.
```go
logger := slog.New(
slog.NewJSONHandler(
os.Stdout,
&slog.HandlerOptions{
ReplaceAttr: masq.New(
// By user defined custom type
masq.WithType[AccessToken](),// By regex of phone number as e164 format
masq.WithRegex(regexp.MustCompile(`^\+[1-9]\d{1,14}$`)),// By field tag such as masq:"secret"
masq.WithTag("secret"),// By by field name prefix. Concealing SecureXxx field
masq.WithFieldPrefix("Secure"),
),
},
),
)
```### With custom type
```go
type password string
type myRecord struct {
ID string
Password password
}
record := myRecord{
ID: "m-mizutani",
Password: "abcd1234",
}logger := slog.New(
slog.NewJSONHandler(
os.Stdout,
&slog.HandlerOptions{
ReplaceAttr: masq.New(masq.WithType[password]()),
},
),
)logger.With("record", record).Info("Got record")
out.Flush()
// Output:
// {"level":"INFO","msg":"Got record","record":{"ID":"m-mizutani","Password":"[FILTERED]"},"time":"2022-12-25T09:00:00.123456789"}
```### With fixed string
```go
const issuedToken = "abcd1234"
authHeader := "Authorization: Bearer " + issuedTokenlogger := slog.New(
slog.NewJSONHandler(
os.Stdout,
&slog.HandlerOptions{
ReplaceAttr: masq.New(masq.WithContain("abcd1234")),
},
),
)logger.With("auth", authHeader).Info("send header")
out.Flush()
// Output:
// {"auth":"[REDACTED]","level":"INFO","msg":"send header","time":"2022-12-25T09:00:00.123456789"}
```## With regex
```go
type myRecord struct {
ID string
Phone string
}
record := myRecord{
ID: "m-mizutani",
Phone: "090-0000-0000",
}logger := slog.New(
slog.NewJSONHandler(
os.Stdout,
&slog.HandlerOptions{
ReplaceAttr: masq.New(masq.WithRegex(regexp.MustCompile(`^\d{3}-\d{4}-\d{4}$`)),
},
),
)logger.With("record", record).Info("Got record")
out.Flush()
// Output:
// {"level":"INFO","msg":"Got record","record":{"ID":"m-mizutani","Phone":"[FILTERED]"},"time":"2022-12-25T09:00:00.123456789"}
```### With struct field tag
```go
type myRecord struct {
ID string
EMail string `masq:"secret"`
}
record := myRecord{
ID: "m-mizutani",
EMail: "[email protected]",
}logger := slog.New(
slog.NewJSONHandler(
os.Stdout,
&slog.HandlerOptions{
ReplaceAttr: masq.New(masq.WithTag("secret")),
},
),
)logger.With("record", record).Info("Got record")
out.Flush()
// Output:
// {"level":"INFO","msg":"Got record","record":{"EMail":"[FILTERED]","ID":"m-mizutani"},"time":"2022-12-25T09:00:00.123456789"}
```You can change the tag key by `masq.WithCustomTagKey` option.
```go
type myRecord struct {
ID string
EMail string `custom:"secret"`
}record := myRecord{
ID: "m-mizutani",
EMail: "[email protected]",
}logger := newLogger(out, masq.New(
masq.WithCustomTagKey("custom"),
masq.WithTag("secret"),
))logger.With("record", record).Info("Got record")
out.Flush()
// Output:
// {"level":"INFO","msg":"Got record","record":{"EMail":"[REDACTED]","ID":"m-mizutani"},"time":"2022-12-25T09:00:00.123456789"}
```### With struct field name
```go
type myRecord struct {
ID string
Phone string
}
record := myRecord{
ID: "m-mizutani",
Phone: "090-0000-0000",
}logger := slog.New(
slog.NewJSONHandler(
os.Stdout,
&slog.HandlerOptions{
ReplaceAttr: masq.New(masq.WithFieldName("Phone")),
},
),
)logger.With("record", record).Info("Got record")
out.Flush()
// Output:
// {"level":"INFO","msg":"Got record","record":{"ID":"m-mizutani","Phone":"[FILTERED]"},"time":"2022-12-25T09:00:00.123456789"}
```### With struct field prefix
```go
type myRecord struct {
ID string
SecurePhone string
}
record := myRecord{
ID: "m-mizutani",
SecurePhone: "090-0000-0000",
}logger := slog.New(
slog.NewJSONHandler(
os.Stdout,
&slog.HandlerOptions{
ReplaceAttr: masq.New(masq.WithFieldPrefix("Secure")),
},
),
)logger.With("record", record).Info("Got record")
out.Flush()
// Output:
// {"level":"INFO","msg":"Got record","record":{"ID":"m-mizutani","SecurePhone":"[FILTERED]"},"time":"2022-12-25T09:00:00.123456789"}
```## License
Apache License v2.0