Hide multi line secrets from log (#671)

close #388
This commit is contained in:
6543 2022-01-08 20:39:52 +01:00 committed by GitHub
parent c186e2fa8c
commit 7986eba002
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 77 additions and 15 deletions

View file

@ -7,6 +7,8 @@ import (
"time" "time"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/woodpecker-ci/woodpecker/pipeline/shared"
) )
// Identifies the type of line in the logs. // Identifies the type of line in the logs.
@ -49,22 +51,14 @@ type LineWriter struct {
// NewLineWriter returns a new line reader. // NewLineWriter returns a new line reader.
func NewLineWriter(peer Peer, id, name string, secret ...string) *LineWriter { func NewLineWriter(peer Peer, id, name string, secret ...string) *LineWriter {
w := new(LineWriter) return &LineWriter{
w.peer = peer peer: peer,
w.id = id id: id,
w.name = name name: name,
w.num = 0 now: time.Now().UTC(),
w.now = time.Now().UTC() rep: shared.NewSecretsReplacer(secret),
lines: nil,
var oldnew []string
for _, old := range secret {
oldnew = append(oldnew, old)
oldnew = append(oldnew, "********")
} }
if len(oldnew) != 0 {
w.rep = strings.NewReplacer(oldnew...)
}
return w
} }
func (w *LineWriter) Write(p []byte) (n int, err error) { func (w *LineWriter) Write(p []byte) (n int, err error) {
@ -72,6 +66,7 @@ func (w *LineWriter) Write(p []byte) (n int, err error) {
if w.rep != nil { if w.rep != nil {
out = w.rep.Replace(out) out = w.rep.Replace(out)
} }
log.Trace().Str("name", w.name).Str("ID", w.id).Msgf("grpc write line: %s", out)
line := &Line{ line := &Line{
Out: out, Out: out,

View file

@ -0,0 +1,34 @@
// Copyright 2022 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shared
import "strings"
func NewSecretsReplacer(secrets []string) *strings.Replacer {
var oldnew []string
for _, old := range secrets {
old = strings.TrimSpace(old)
if len(old) == 0 {
continue
}
// since replacer is executed on each line we have to split multi-line-secrets
for _, part := range strings.Split(old, "\n") {
oldnew = append(oldnew, part)
oldnew = append(oldnew, "********")
}
}
return strings.NewReplacer(oldnew...)
}

View file

@ -0,0 +1,33 @@
package shared
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewSecretsReplacer(t *testing.T) {
tc := []struct {
log string
secrets []string
expect string
}{{
log: "start log\ndone",
secrets: []string{""},
expect: "start log\ndone",
}, {
log: `this IS secret: password`,
secrets: []string{"password", " IS "},
expect: `this ******** secret: ********`,
}, {
log: "start log\ndone\nnow\nan\nmulti line secret!! ;)",
secrets: []string{"an\nmulti line secret!!"},
expect: "start log\ndone\nnow\n********\n******** ;)",
}}
for _, c := range tc {
rep := NewSecretsReplacer(c.secrets)
result := rep.Replace(c.log)
assert.EqualValues(t, c.expect, result)
}
}