Skip to content

Commit e5d55d7

Browse files
authored
Revert "[redact] change RedactText to operate on []byte" (#10561)
Reverts #10543
1 parent 61a11c2 commit e5d55d7

File tree

3 files changed

+54
-67
lines changed

3 files changed

+54
-67
lines changed

enterprise/server/cmd/ci_runner/main.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,8 @@ func (r *buildEventReporter) Start(startTime time.Time) error {
451451
return err
452452
}
453453

454-
r.log.writeListener = func(b []byte) {
455-
r.emitBuildEventsForBazelCommands(b)
454+
r.log.writeListener = func(s string) {
455+
r.emitBuildEventsForBazelCommands(s)
456456
// Flush whenever the log buffer fills past a certain threshold.
457457
if size := r.log.Len(); size >= progressFlushThresholdBytes {
458458
r.FlushProgress() // ignore error; it will surface in `bep.Finish()`
@@ -574,11 +574,11 @@ func (r *buildEventReporter) startBackgroundProgressFlush() func() {
574574
//
575575
// Event publishing errors will be surfaced in the caller func when calling
576576
// `buildEventPublisher.Finish()`
577-
func (r *buildEventReporter) emitBuildEventsForBazelCommands(output []byte) {
577+
func (r *buildEventReporter) emitBuildEventsForBazelCommands(output string) {
578578
// Check whether a bazel invocation was invoked
579-
iidMatches := invocationIDRegex.FindAllSubmatch(output, -1)
579+
iidMatches := invocationIDRegex.FindAllStringSubmatch(output, -1)
580580
for _, m := range iidMatches {
581-
iid := string(m[1])
581+
iid := m[1]
582582
childStarted := slices.Contains(r.childInvocations, iid)
583583

584584
var buildEvent *bespb.BuildEvent
@@ -937,20 +937,22 @@ func (r *buildEventReporter) Printf(format string, vals ...interface{}) {
937937
type invocationLog struct {
938938
lockingbuffer.LockingBuffer
939939
writer io.Writer
940-
writeListener func(b []byte)
940+
writeListener func(s string)
941941
}
942942

943943
func newInvocationLog() *invocationLog {
944-
invLog := &invocationLog{writeListener: func(b []byte) {}}
944+
invLog := &invocationLog{writeListener: func(s string) {}}
945945
invLog.writer = io.MultiWriter(&invLog.LockingBuffer, os.Stderr)
946946
return invLog
947947
}
948948

949949
func (invLog *invocationLog) Write(b []byte) (int, error) {
950-
redacted := redact.RedactText(b)
950+
output := string(b)
951+
952+
redacted := redact.RedactText(output)
951953

952954
invLog.writeListener(redacted)
953-
_, err := invLog.writer.Write(redacted)
955+
_, err := invLog.writer.Write([]byte(redacted))
954956

955957
// Return the size of the original buffer even if a redacted size was written,
956958
// or clients will return a short write error

server/util/redact/redact.go

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package redact
22

33
import (
4-
"bytes"
54
"context"
65
"encoding/base64"
76
"encoding/json"
@@ -114,11 +113,7 @@ func init() {
114113
}
115114

116115
func stripURLSecrets(input string) string {
117-
return string(stripURLSecretsBytes([]byte(input)))
118-
}
119-
120-
func stripURLSecretsBytes(input []byte) []byte {
121-
return urlSecretRegex.ReplaceAll(input, []byte("${1}<REDACTED>${2}"))
116+
return urlSecretRegex.ReplaceAllString(input, "${1}<REDACTED>${2}")
122117
}
123118

124119
// Strips URL secrets from the provided flag value, if there is a value.
@@ -233,57 +228,45 @@ func redactCmdLine(tokens []string) {
233228
stripNonAllowedEnvVars(tokens)
234229
}
235230

236-
func RedactText(b []byte) []byte {
237-
b = stripURLSecretsBytes(b)
238-
b = redactRemoteHeadersBytes(b)
239-
b = redactBuildBuddyAPIKeysBytes(b)
240-
b = redactEnvVarsBytes(b)
241-
return b
231+
func RedactText(txt string) string {
232+
txt = stripURLSecrets(txt)
233+
txt = redactRemoteHeaders(txt)
234+
txt = redactBuildBuddyAPIKeys(txt)
235+
txt = redactEnvVars(txt)
236+
return txt
242237
}
243238

244239
// redactBuildBuddyAPIKeys redacts BuildBuddy API keys in the input string.
245240
// It looks for HTTP headers, URL secrets, environment variables, and the configured API key.
246241
// This implementation depends on BuildBuddy API keys being exactly 20 alphanumeric characters.
247242
func redactBuildBuddyAPIKeys(txt string) string {
248-
return string(redactBuildBuddyAPIKeysBytes([]byte(txt)))
249-
}
250-
251-
func redactBuildBuddyAPIKeysBytes(b []byte) []byte {
252243
// Replace x-buildbuddy-api-key header.
253-
b = apiKeyHeaderPattern.ReplaceAllLiteral(b, []byte("x-buildbuddy-api-key=<REDACTED>"))
244+
txt = apiKeyHeaderPattern.ReplaceAllLiteralString(txt, "x-buildbuddy-api-key=<REDACTED>")
254245

255246
// Replace sequences that look like API keys immediately followed by '@',
256247
// to account for patterns like "grpc://$API_KEY@app.buildbuddy.io"
257248
// or "bes_backend=$API_KEY@domain.com".
258-
b = apiKeyAtPattern.ReplaceAll(b, []byte("$1<REDACTED>@"))
249+
txt = apiKeyAtPattern.ReplaceAllString(txt, "$1<REDACTED>@")
259250

260251
// Replace the literal API key set up via the BuildBuddy config, which does not
261252
// need to conform to the way we generate API keys.
262253
if configuredKey := *apiKey; configuredKey != "" {
263-
b = bytes.ReplaceAll(b, []byte(configuredKey), []byte("<REDACTED>"))
254+
txt = strings.ReplaceAll(txt, configuredKey, "<REDACTED>")
264255
}
265256

266-
return b
257+
return txt
267258
}
268259

269260
func redactRemoteHeaders(txt string) string {
270-
return string(redactRemoteHeadersBytes([]byte(txt)))
271-
}
272-
273-
func redactRemoteHeadersBytes(b []byte) []byte {
274261
for _, header := range headerOptionNames {
275262
regex := regexp.MustCompile(fmt.Sprintf("--%s=[^\\s]+", header))
276-
b = regex.ReplaceAllLiteral(b, []byte(fmt.Sprintf("--%s=<REDACTED>", header)))
263+
txt = regex.ReplaceAllLiteralString(txt, fmt.Sprintf("--%s=<REDACTED>", header))
277264
}
278-
return b
265+
return txt
279266
}
280267

281268
func redactEnvVars(txt string) string {
282-
return string(redactEnvVarsBytes([]byte(txt)))
283-
}
284-
285-
func redactEnvVarsBytes(b []byte) []byte {
286-
return envVarOptionNamesRegex.ReplaceAll(b, []byte("${1}<REDACTED>"))
269+
return envVarOptionNamesRegex.ReplaceAllString(txt, "${1}<REDACTED>")
287270
}
288271

289272
func stripURLSecretsFromFile(file *bespb.File) *bespb.File {
@@ -445,8 +428,8 @@ func redactStructuredCommandLine(commandLine *clpb.CommandLine, allowedEnvVars [
445428
if err != nil {
446429
return status.WrapError(err, "decode serialized action")
447430
}
448-
redactedAction := RedactText(decodedAction)
449-
option.OptionValue = base64.StdEncoding.EncodeToString(redactedAction)
431+
redactedAction := RedactText(string(decodedAction))
432+
option.OptionValue = base64.StdEncoding.EncodeToString([]byte(redactedAction))
450433
}
451434
}
452435
continue

server/util/redact/redact_test.go

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -639,33 +639,35 @@ func TestRedactRunResidual(t *testing.T) {
639639
func TestRedactTxt(t *testing.T) {
640640
for _, tc := range []struct {
641641
name string
642-
txt []byte
643-
expected []byte
642+
txt string
643+
expected string
644644
}{
645645
{
646646
name: "remote headers",
647-
txt: []byte("ok --remote_header=x-buildbuddy-api-key=secret --flag=ok"),
648-
expected: []byte("ok --remote_header=<REDACTED> --flag=ok"),
647+
txt: "ok --remote_header=x-buildbuddy-api-key=secret --flag=ok",
648+
expected: "ok --remote_header=<REDACTED> --flag=ok",
649649
},
650650
{
651651
name: "url secrets",
652-
txt: []byte("ok url://username:password@uri --flag=ok"),
653-
expected: []byte("ok url://username:<REDACTED>@uri --flag=ok"),
652+
txt: "ok url://username:password@uri --flag=ok",
653+
expected: "ok url://username:<REDACTED>@uri --flag=ok",
654654
},
655655
{
656656
name: "do not redact rules names",
657-
txt: []byte("ERROR: Error computing the main repository mapping: rules_apple@3.16.1 depends on rules_swift@2.1.1 with compatibility level 2, but <root> depends on rules_swift@1.18.0 with compatibility level 1 which is different"),
658-
expected: []byte("ERROR: Error computing the main repository mapping: rules_apple@3.16.1 depends on rules_swift@2.1.1 with compatibility level 2, but <root> depends on rules_swift@1.18.0 with compatibility level 1 which is different"),
657+
txt: "ERROR: Error computing the main repository mapping: rules_apple@3.16.1 depends on rules_swift@2.1.1 with compatibility level 2, but <root> depends on rules_swift@1.18.0 with compatibility level 1 which is different",
658+
expected: "ERROR: Error computing the main repository mapping: rules_apple@3.16.1 depends on rules_swift@2.1.1 with compatibility level 2, but <root> depends on rules_swift@1.18.0 with compatibility level 1 which is different",
659659
},
660660
{
661661
name: "api key start of line",
662-
txt: []byte("apikeyexactly20chars@mydomain.com"),
663-
expected: []byte("<REDACTED>@mydomain.com"),
662+
txt: "apikeyexactly20chars@mydomain.com",
663+
expected: "<REDACTED>@mydomain.com",
664664
},
665665
{
666-
name: "environment variables",
667-
txt: []byte("common --repo_env=AWS_ACCESS_KEY_ID=super_secret_access_key_id # gitleaks:allow\ncommon --repo_env=AWS_SECRET_ACCESS_KEY=super_secret_access_key # gitleaks:allow"),
668-
expected: []byte("common --repo_env=AWS_ACCESS_KEY_ID=<REDACTED> # gitleaks:allow\ncommon --repo_env=AWS_SECRET_ACCESS_KEY=<REDACTED> # gitleaks:allow"),
666+
name: "environment variables",
667+
txt: "common --repo_env=AWS_ACCESS_KEY_ID=super_secret_access_key_id # gitleaks:allow\n" +
668+
"common --repo_env=AWS_SECRET_ACCESS_KEY=super_secret_access_key # gitleaks:allow",
669+
expected: "common --repo_env=AWS_ACCESS_KEY_ID=<REDACTED> # gitleaks:allow\n" +
670+
"common --repo_env=AWS_SECRET_ACCESS_KEY=<REDACTED> # gitleaks:allow",
669671
},
670672
} {
671673
t.Run(tc.name, func(t *testing.T) {
@@ -678,28 +680,28 @@ func TestRedactTxt(t *testing.T) {
678680
func TestRedactAPIKeys(t *testing.T) {
679681
for _, tc := range []struct {
680682
name string
681-
txt []byte
682-
expected []byte
683+
txt string
684+
expected string
683685
}{
684686
{
685687
name: "api key after equals",
686-
txt: []byte("MY_SECRET_API_KEY=apikeyexactly20chars@mydomain.com"),
687-
expected: []byte("MY_SECRET_API_KEY=<REDACTED>@mydomain.com"),
688+
txt: "MY_SECRET_API_KEY=apikeyexactly20chars@mydomain.com",
689+
expected: "MY_SECRET_API_KEY=<REDACTED>@mydomain.com",
688690
},
689691
{
690692
name: "api key in grpc call",
691-
txt: []byte("grpc://apikeyexactly20chars@mydomain.com"),
692-
expected: []byte("grpc://<REDACTED>@mydomain.com"),
693+
txt: "grpc://apikeyexactly20chars@mydomain.com",
694+
expected: "grpc://<REDACTED>@mydomain.com",
693695
},
694696
{
695697
name: "api key in http call",
696-
txt: []byte("https://apikeyexactly20chars@mydomain.com"),
697-
expected: []byte("https://<REDACTED>@mydomain.com"),
698+
txt: "https://apikeyexactly20chars@mydomain.com",
699+
expected: "https://<REDACTED>@mydomain.com",
698700
},
699701
{
700702
name: "do not redact text before bazel repository name",
701-
txt: []byte("FAILED:exactly20alphanumber@@apple_support++apple_cc_configure_extension+local_config_apple_cc; starting"),
702-
expected: []byte("FAILED:exactly20alphanumber@@apple_support++apple_cc_configure_extension+local_config_apple_cc; starting"),
703+
txt: "FAILED:exactly20alphanumber@@apple_support++apple_cc_configure_extension+local_config_apple_cc; starting",
704+
expected: "FAILED:exactly20alphanumber@@apple_support++apple_cc_configure_extension+local_config_apple_cc; starting",
703705
},
704706
} {
705707
t.Run(tc.name, func(t *testing.T) {
@@ -709,14 +711,14 @@ func TestRedactAPIKeys(t *testing.T) {
709711
event := &bespb.BuildEvent{
710712
Payload: &bespb.BuildEvent_Progress{
711713
Progress: &bespb.Progress{
712-
Stdout: string(tc.txt),
714+
Stdout: tc.txt,
713715
},
714716
},
715717
}
716718
redactor := redact.NewStreamingRedactor(testenv.GetTestEnv(t))
717719
err := redactor.RedactAPIKeysWithSlowRegexp(context.TODO(), event)
718720
require.NoError(t, err)
719-
require.Equal(t, string(tc.expected), event.GetProgress().GetStdout())
721+
require.Equal(t, tc.expected, event.GetProgress().GetStdout())
720722
})
721723
}
722724
}

0 commit comments

Comments
 (0)