Redact no_log task results
This commit is contained in:
parent
f233605542
commit
89eee7b964
2 changed files with 109 additions and 2 deletions
42
executor.go
42
executor.go
|
|
@ -602,13 +602,18 @@ func (e *Executor) runTaskOnHost(ctx context.Context, host string, hosts []strin
|
|||
e.results[host][task.Register] = result
|
||||
}
|
||||
|
||||
displayResult := result
|
||||
if task.NoLog {
|
||||
displayResult = redactTaskResult(result)
|
||||
}
|
||||
|
||||
// Handle notify
|
||||
if result.Changed && task.Notify != nil {
|
||||
e.handleNotify(task.Notify)
|
||||
}
|
||||
|
||||
if e.OnTaskEnd != nil {
|
||||
e.OnTaskEnd(host, task, result)
|
||||
e.OnTaskEnd(host, task, displayResult)
|
||||
}
|
||||
|
||||
if NormalizeModule(task.Module) == "ansible.builtin.meta" {
|
||||
|
|
@ -619,7 +624,7 @@ func (e *Executor) runTaskOnHost(ctx context.Context, host string, hosts []strin
|
|||
|
||||
if result.Failed && !task.IgnoreErrors {
|
||||
e.markBatchHostFailed(host)
|
||||
return coreerr.E("Executor.runTaskOnHost", "task failed: "+result.Msg, nil)
|
||||
return taskFailureError(task, result)
|
||||
}
|
||||
if result.Failed {
|
||||
e.markBatchHostFailed(host)
|
||||
|
|
@ -663,6 +668,39 @@ func (e *Executor) checkMaxFailPercentage(play *Play, hosts []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func redactTaskResult(result *TaskResult) *TaskResult {
|
||||
if result == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
redacted := *result
|
||||
redacted.Msg = "censored due to no_log"
|
||||
redacted.Stdout = ""
|
||||
redacted.Stderr = ""
|
||||
redacted.Data = nil
|
||||
if len(result.Results) > 0 {
|
||||
redacted.Results = make([]TaskResult, len(result.Results))
|
||||
for i := range result.Results {
|
||||
redacted.Results[i] = *redactTaskResult(&result.Results[i])
|
||||
}
|
||||
}
|
||||
|
||||
return &redacted
|
||||
}
|
||||
|
||||
func taskFailureError(task *Task, result *TaskResult) error {
|
||||
if task != nil && task.NoLog {
|
||||
return coreerr.E("Executor.runTaskOnHost", "task failed", nil)
|
||||
}
|
||||
|
||||
msg := "task failed"
|
||||
if result != nil && result.Msg != "" {
|
||||
msg += ": " + result.Msg
|
||||
}
|
||||
|
||||
return coreerr.E("Executor.runTaskOnHost", msg, nil)
|
||||
}
|
||||
|
||||
// runTaskWithRetries executes a task once or multiple times when retries,
|
||||
// delay, or until are configured.
|
||||
func (e *Executor) runTaskWithRetries(ctx context.Context, host string, task *Task, play *Play, execute func() (*TaskResult, error)) (*TaskResult, error) {
|
||||
|
|
|
|||
|
|
@ -635,6 +635,75 @@ func TestExecutor_RunTaskOnHost_Good_CheckModeSkipsMutatingTask(t *testing.T) {
|
|||
assert.True(t, e.results["host1"]["shell_result"].Skipped)
|
||||
}
|
||||
|
||||
// --- no_log ---
|
||||
|
||||
func TestExecutor_RunTaskOnHost_Good_NoLogRedactsCallbackResult(t *testing.T) {
|
||||
e := NewExecutor("/tmp")
|
||||
e.SetInventoryDirect(&Inventory{
|
||||
All: &InventoryGroup{
|
||||
Hosts: map[string]*Host{
|
||||
"host1": {},
|
||||
},
|
||||
},
|
||||
})
|
||||
e.clients["host1"] = &SSHClient{}
|
||||
|
||||
var ended *TaskResult
|
||||
task := &Task{
|
||||
Name: "Sensitive debug",
|
||||
Module: "debug",
|
||||
Args: map[string]any{"msg": "top secret"},
|
||||
Register: "debug_result",
|
||||
NoLog: true,
|
||||
}
|
||||
|
||||
e.OnTaskEnd = func(_ string, _ *Task, result *TaskResult) {
|
||||
ended = result
|
||||
}
|
||||
|
||||
err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, ended)
|
||||
assert.Equal(t, "censored due to no_log", ended.Msg)
|
||||
assert.Empty(t, ended.Stdout)
|
||||
assert.Empty(t, ended.Stderr)
|
||||
assert.Nil(t, ended.Data)
|
||||
require.NotNil(t, e.results["host1"]["debug_result"])
|
||||
assert.Equal(t, "top secret", e.results["host1"]["debug_result"].Msg)
|
||||
}
|
||||
|
||||
func TestExecutor_RunTaskOnHost_Bad_NoLogHidesFailureMessage(t *testing.T) {
|
||||
e := NewExecutor("/tmp")
|
||||
e.SetInventoryDirect(&Inventory{
|
||||
All: &InventoryGroup{
|
||||
Hosts: map[string]*Host{
|
||||
"host1": {},
|
||||
},
|
||||
},
|
||||
})
|
||||
e.clients["host1"] = &SSHClient{}
|
||||
|
||||
var ended *TaskResult
|
||||
task := &Task{
|
||||
Name: "Sensitive failure",
|
||||
Module: "fail",
|
||||
Args: map[string]any{"msg": "super secret"},
|
||||
NoLog: true,
|
||||
}
|
||||
|
||||
e.OnTaskEnd = func(_ string, _ *Task, result *TaskResult) {
|
||||
ended = result
|
||||
}
|
||||
|
||||
err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{})
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "task failed")
|
||||
assert.NotContains(t, err.Error(), "super secret")
|
||||
require.NotNil(t, ended)
|
||||
assert.Equal(t, "censored due to no_log", ended.Msg)
|
||||
}
|
||||
|
||||
// --- normalizeConditions ---
|
||||
|
||||
func TestExecutor_NormalizeConditions_Good_String(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue