mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-08-27 00:37:20 +00:00
fix(preflight): redact local host preflight collector output (#2101)
CollectHostWithContext was the only collection path (in-cluster support bundle, remote/SSH host collectors) that never ran collected data through the redaction engine. A `run` collector's captured environment in particular can carry credentials verbatim -- e.g. HTTPS_PROXY with embedded Basic Auth -- straight into the bundle's <collectorName>-info.json with no redaction applied. Wire it through collect.RedactResult the same way CollectRemoteWithContext and pkg/supportbundle/collect.go already do, so the built-in default redactors apply to local host preflight output too. Fixes #2100
This commit is contained in:
@@ -145,6 +145,15 @@ func CollectHostWithContext(
|
||||
span.End()
|
||||
}
|
||||
|
||||
// Local host preflight collectors are the only collection path (cluster,
|
||||
// remote host, in-cluster support bundle) that skipped redaction entirely.
|
||||
// A `run` collector's captured environment in particular can carry
|
||||
// credentials verbatim (e.g. HTTPS_PROXY with embedded Basic Auth) into
|
||||
// the bundle. See https://github.com/replicatedhq/troubleshoot/issues/2100.
|
||||
if err := collect.RedactResult(opts.BundlePath, collect.CollectorResult(allCollectedData), nil); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to redact host collector results")
|
||||
}
|
||||
|
||||
// The values of map entries will contain the collected data in bytes if the data was not stored to disk
|
||||
collectResult.AllCollectedData = allCollectedData
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -209,3 +212,46 @@ func TestCollectWithContext_PreservesOrderAfterClusterResources(t *testing.T) {
|
||||
assert.Less(t, dataIndex, secretIndex, "data collectors should come before secret collectors, preserving relative order")
|
||||
}
|
||||
}
|
||||
|
||||
// TestCollectHostWithContext_RedactsSensitiveEnvValues verifies that a `run`
|
||||
// host collector's captured environment is redacted before being written to
|
||||
// the bundle. CollectHostWithContext is the only collection path (cluster,
|
||||
// host, remote) that skipped redaction entirely: every env var passed to the
|
||||
// command -- including credentials embedded in a proxy URL -- landed
|
||||
// verbatim in <collectorName>-info.json.
|
||||
func TestCollectHostWithContext_RedactsSensitiveEnvValues(t *testing.T) {
|
||||
bundlePath := t.TempDir()
|
||||
|
||||
hostPreflight := &troubleshootv1beta2.HostPreflight{
|
||||
Spec: troubleshootv1beta2.HostPreflightSpec{
|
||||
Collectors: []*troubleshootv1beta2.HostCollect{
|
||||
{
|
||||
HostRun: &troubleshootv1beta2.HostRun{
|
||||
HostCollectorMeta: troubleshootv1beta2.HostCollectorMeta{
|
||||
CollectorName: "proxy-credential-check",
|
||||
},
|
||||
Command: "sh",
|
||||
Args: []string{"-c", "echo ok"},
|
||||
IgnoreParentEnvs: true,
|
||||
Env: []string{
|
||||
"HTTPS_PROXY=http://alice:sw0rdfish@proxy.example.com:3128",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := CollectHostWithContext(context.Background(), CollectOpts{
|
||||
ProgressChan: make(chan interface{}, 100),
|
||||
BundlePath: bundlePath,
|
||||
}, hostPreflight)
|
||||
require.NoError(t, err)
|
||||
|
||||
infoPath := filepath.Join(bundlePath, "host-collectors/run-host/proxy-credential-check-info.json")
|
||||
b, err := os.ReadFile(infoPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NotContains(t, string(b), "sw0rdfish", "proxy credential leaked unredacted into the host preflight bundle")
|
||||
assert.Contains(t, string(b), "***HIDDEN***", "expected the built-in URL-userinfo redactor to mask the credential")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user