Skip to content

Commit

Permalink
log writer support mask replace to hidden secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
zc2638 committed Mar 20, 2024
1 parent 5136709 commit df8c04d
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ linters-settings:
threshold: 200
funlen:
lines: -1
statements: 100
statements: 150
gci:
skip-generated: true
custom-order: true
Expand Down
68 changes: 68 additions & 0 deletions core/worker/runtime/replacer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright © 2024 zc2638 <zc2638@qq.com>.
//
// 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 runtime

import (
"io"
"strings"
)

// maskReplacer is an io.Writer that finds and masks sensitive data.
type maskReplacer struct {
w io.WriteCloser
r *strings.Replacer
}

// NewMaskReplacer returns a replacer that wraps io.Writer w.
func NewMaskReplacer(w io.WriteCloser, values []string) io.WriteCloser {
var oldnew []string
for _, v := range values {
if len(v) == 0 {
continue
}

for _, part := range strings.Split(v, "\n") {
part = strings.TrimSpace(part)

// avoid masking empty or single character strings.
if len(part) < 2 {
continue
}

masked := "******"
oldnew = append(oldnew, part)
oldnew = append(oldnew, masked)
}
}
if len(oldnew) == 0 {
return w
}
return &maskReplacer{
w: w,
r: strings.NewReplacer(oldnew...),
}
}

// Write writes p to the base writer. The method scans for any
// sensitive data in p and masks before writing.
func (r *maskReplacer) Write(p []byte) (n int, err error) {
_, err = r.w.Write([]byte(r.r.Replace(string(p))))
return len(p), err
}

// Close closes the base writer.
func (r *maskReplacer) Close() error {
return r.w.Close()
}
23 changes: 23 additions & 0 deletions core/worker/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ import (
"math"
"time"

"github.com/99nil/gopkg/sets"
"github.com/zc2638/wslog"
"golang.org/x/sync/errgroup"

"github.com/zc2638/ink/core/clients"
"github.com/zc2638/ink/core/constant"
"github.com/zc2638/ink/core/worker/runtime"
v1 "github.com/zc2638/ink/pkg/api/core/v1"
"github.com/zc2638/ink/pkg/livelog"
)
Expand Down Expand Up @@ -210,6 +212,26 @@ func execute(
return nil
}

secretValueSet := sets.New[string]()
for _, secret := range secrets {
if err := secret.Decrypt(); err == nil {
status.Phase = v1.PhaseFailed
status.Error = err.Error()
for _, step := range status.Steps {
step.Phase = v1.PhaseSkipped
step.Started = status.Started
}
if err := client.StageEnd(ctx, status); err != nil {
return fmt.Errorf("stage end failed: %v", err)
}
return nil
}
for _, v := range secret.Data {
secretValueSet.Add(v)
}
}
secretValueList := secretValueSet.List()

var (
failed bool
canceled bool
Expand Down Expand Up @@ -278,6 +300,7 @@ func execute(
}
}
wc := livelog.NewWriter(logHandle)
wc = runtime.NewMaskReplacer(wc, secretValueList)

stepLog.Debug("Execute step hook")
state, err := hook.Step(ctx, spec, stepSpec, wc)
Expand Down

0 comments on commit df8c04d

Please sign in to comment.