mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: redact env var values in agent debug manifest endpoint (#26904)
This commit is contained in:
+23
-1
@@ -2291,12 +2291,34 @@ func (a *agent) HandleHTTPDebugManifest(w http.ResponseWriter, r *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
// Redact env values. This endpoint is unauthenticated on loopback,
|
||||
// reachable by any process regardless of Unix user. Keys are preserved
|
||||
// so operators can still see which variables are configured.
|
||||
debugManifest := *sdkManifest
|
||||
if len(sdkManifest.EnvironmentVariables) > 0 {
|
||||
envs := make(map[string]string, len(sdkManifest.EnvironmentVariables))
|
||||
for k, v := range sdkManifest.EnvironmentVariables {
|
||||
// Preserve empty values, which carry no secret, matching
|
||||
// sanitizeEnv in support/support.go.
|
||||
if v == "" {
|
||||
envs[k] = v
|
||||
continue
|
||||
}
|
||||
envs[k] = redactedManifestEnvValue
|
||||
}
|
||||
debugManifest.EnvironmentVariables = envs
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if err := json.NewEncoder(w).Encode(sdkManifest); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(debugManifest); err != nil {
|
||||
a.logger.Error(a.hardCtx, "write debug manifest", slog.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
// redactedManifestEnvValue matches the marker used by sanitizeEnv in
|
||||
// support/support.go so a support bundle and this endpoint agree.
|
||||
const redactedManifestEnvValue = "***REDACTED***"
|
||||
|
||||
func (a *agent) HTTPDebug() http.Handler {
|
||||
r := chi.NewRouter()
|
||||
|
||||
|
||||
@@ -3672,6 +3672,10 @@ func TestAgent_DebugServer(t *testing.T) {
|
||||
//nolint:dogsled
|
||||
conn, _, _, _, agnt := setupAgentWithSecrets(t, agentsdk.Manifest{
|
||||
DERPMap: derpMap,
|
||||
EnvironmentVariables: map[string]string{
|
||||
"AWS_SECRET_ACCESS_KEY": "env-value-should-be-redacted-67890",
|
||||
"EMPTY_VAR": "",
|
||||
},
|
||||
}, []agentsdk.WorkspaceSecret{
|
||||
{EnvName: "DEBUG_SECRET", Value: []byte("super-secret-value-12345")},
|
||||
}, 0, func(c *agenttest.Client, o *agent.Options) {
|
||||
@@ -3800,6 +3804,34 @@ func TestAgent_DebugServer(t *testing.T) {
|
||||
require.NoError(t, json.Unmarshal(body, &v))
|
||||
})
|
||||
|
||||
t.Run("ManifestEnvVarValuesRedacted", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL+"/debug/manifest", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := srv.Client().Do(req)
|
||||
require.NoError(t, err)
|
||||
defer res.Body.Close()
|
||||
require.Equal(t, http.StatusOK, res.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotContains(t, string(body), "env-value-should-be-redacted-67890")
|
||||
|
||||
var v agentsdk.Manifest
|
||||
require.NoError(t, json.Unmarshal(body, &v))
|
||||
|
||||
require.Contains(t, v.EnvironmentVariables, "AWS_SECRET_ACCESS_KEY")
|
||||
require.Equal(t, "***REDACTED***", v.EnvironmentVariables["AWS_SECRET_ACCESS_KEY"])
|
||||
|
||||
// Empty values carry no secret and are preserved as empty.
|
||||
require.Contains(t, v.EnvironmentVariables, "EMPTY_VAR")
|
||||
require.Equal(t, "", v.EnvironmentVariables["EMPTY_VAR"])
|
||||
})
|
||||
|
||||
t.Run("Logs", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user