Strip Userinfo from log entries and errors #2051
This commit is contained in:
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/AlexxIT/go2rtc/internal/api"
|
"github.com/AlexxIT/go2rtc/internal/api"
|
||||||
"github.com/AlexxIT/go2rtc/internal/app"
|
"github.com/AlexxIT/go2rtc/internal/app"
|
||||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
"github.com/AlexxIT/go2rtc/pkg/creds"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
@@ -133,7 +133,7 @@ func apiWS(w http.ResponseWriter, r *http.Request) {
|
|||||||
if handler := wsHandlers[msg.Type]; handler != nil {
|
if handler := wsHandlers[msg.Type]; handler != nil {
|
||||||
go func() {
|
go func() {
|
||||||
if err = handler(tr, msg); err != nil {
|
if err = handler(tr, msg); err != nil {
|
||||||
errMsg := core.StripUserinfo(err.Error())
|
errMsg := creds.SecretString(err.Error())
|
||||||
tr.Write(&Message{Type: "error", Value: msg.Type + ": " + errMsg})
|
tr.Write(&Message{Type: "error", Value: msg.Type + ": " + errMsg})
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -93,14 +92,3 @@ func Caller() string {
|
|||||||
_, file, line, _ := runtime.Caller(1)
|
_, file, line, _ := runtime.Caller(1)
|
||||||
return file + ":" + strconv.Itoa(line)
|
return file + ":" + strconv.Itoa(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
unreserved = `A-Za-z0-9-._~`
|
|
||||||
subdelims = `!$&'()*+,;=`
|
|
||||||
userinfo = unreserved + subdelims + `%:`
|
|
||||||
)
|
|
||||||
|
|
||||||
func StripUserinfo(s string) string {
|
|
||||||
sanitizer := regexp.MustCompile(`://[` + userinfo + `]+@`)
|
|
||||||
return sanitizer.ReplaceAllString(s, `://***@`)
|
|
||||||
}
|
|
||||||
|
|||||||
+30
-19
@@ -3,6 +3,7 @@ package creds
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -27,6 +28,7 @@ func AddSecret(value string) {
|
|||||||
var secrets []string
|
var secrets []string
|
||||||
var secretsMu sync.Mutex
|
var secretsMu sync.Mutex
|
||||||
var secretsReplacer *strings.Replacer
|
var secretsReplacer *strings.Replacer
|
||||||
|
var userinfoRegexp *regexp.Regexp
|
||||||
|
|
||||||
func getReplacer() *strings.Replacer {
|
func getReplacer() *strings.Replacer {
|
||||||
secretsMu.Lock()
|
secretsMu.Lock()
|
||||||
@@ -40,14 +42,33 @@ func getReplacer() *strings.Replacer {
|
|||||||
secretsReplacer = strings.NewReplacer(oldnew...)
|
secretsReplacer = strings.NewReplacer(oldnew...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if userinfoRegexp == nil {
|
||||||
|
userinfoRegexp = regexp.MustCompile(`://[` + userinfo + `]+@`)
|
||||||
|
}
|
||||||
|
|
||||||
return secretsReplacer
|
return secretsReplacer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uniform Resource Identifier (URI)
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc3986
|
||||||
|
const (
|
||||||
|
unreserved = `A-Za-z0-9-._~`
|
||||||
|
subdelims = `!$&'()*+,;=`
|
||||||
|
userinfo = unreserved + subdelims + `%:`
|
||||||
|
)
|
||||||
|
|
||||||
func SecretString(s string) string {
|
func SecretString(s string) string {
|
||||||
re := getReplacer()
|
re := getReplacer()
|
||||||
|
s = userinfoRegexp.ReplaceAllString(s, `://***@`)
|
||||||
return re.Replace(s)
|
return re.Replace(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SecretWrite(w io.Writer, s string) (n int, err error) {
|
||||||
|
re := getReplacer()
|
||||||
|
s = userinfoRegexp.ReplaceAllString(s, `://***@`)
|
||||||
|
return re.WriteString(w, s)
|
||||||
|
}
|
||||||
|
|
||||||
func SecretWriter(w io.Writer) io.Writer {
|
func SecretWriter(w io.Writer) io.Writer {
|
||||||
return &secretWriter{w}
|
return &secretWriter{w}
|
||||||
}
|
}
|
||||||
@@ -57,27 +78,17 @@ type secretWriter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *secretWriter) Write(b []byte) (int, error) {
|
func (s *secretWriter) Write(b []byte) (int, error) {
|
||||||
re := getReplacer()
|
return SecretWrite(s.w, string(b))
|
||||||
return re.WriteString(s.w, string(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
type secretResponse struct {
|
|
||||||
w http.ResponseWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *secretResponse) Header() http.Header {
|
|
||||||
return s.w.Header()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *secretResponse) Write(b []byte) (int, error) {
|
|
||||||
re := getReplacer()
|
|
||||||
return re.WriteString(s.w, string(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *secretResponse) WriteHeader(statusCode int) {
|
|
||||||
s.w.WriteHeader(statusCode)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SecretResponse(w http.ResponseWriter) http.ResponseWriter {
|
func SecretResponse(w http.ResponseWriter) http.ResponseWriter {
|
||||||
return &secretResponse{w}
|
return &secretResponse{w}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type secretResponse struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *secretResponse) Write(b []byte) (int, error) {
|
||||||
|
return SecretWrite(s.ResponseWriter, string(b))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user