From 342eb60ae748e196650174131837f1121a76330b Mon Sep 17 00:00:00 2001 From: Umputun Date: Tue, 18 Jul 2023 12:24:14 -0500 Subject: [PATCH] prevent single-line sudo command to run in dbl-shell --- pkg/runner/commands.go | 6 +++++- pkg/runner/runner_test.go | 23 +++++++++++++++++++++-- pkg/runner/testdata/conf.yml | 5 +++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/pkg/runner/commands.go b/pkg/runner/commands.go index 2f29521f..3ce2fd7b 100644 --- a/pkg/runner/commands.go +++ b/pkg/runner/commands.go @@ -78,7 +78,11 @@ func (ec *execCmd) Script(ctx context.Context) (resp execCmdResp, err error) { resp.details = fmt.Sprintf(" {script: %s}", c) if ec.cmd.Options.Sudo { resp.details = fmt.Sprintf(" {script: %s, sudo: true}", c) - c = fmt.Sprintf("sudo sh -c %q", c) + if strings.HasPrefix(c, "sh -c ") { // single line script already has sh -c + c = fmt.Sprintf("sudo %s", c) + } else { + c = fmt.Sprintf("sudo sh -c %q", c) + } } resp.verbose = scr diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index 7907d2c9..794b56aa 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -222,10 +222,10 @@ func TestProcess_Run(t *testing.T) { conf, err := config.New("testdata/conf.yml", nil, nil) require.NoError(t, err) - cmd := conf.Tasks[0].Commands[18] + cmd := conf.Tasks[0].Commands[19] assert.Equal(t, "copy filename from env", cmd.Name) cmd.Environment = map[string]string{"filename": "testdata/conf.yml"} - conf.Tasks[0].Commands[18] = cmd + conf.Tasks[0].Commands[19] = cmd p := Process{ Concurrency: 1, @@ -340,6 +340,25 @@ func TestProcess_RunWithSudo(t *testing.T) { assert.Contains(t, outWriter.String(), "passwd") }) + t.Run("single line script with var", func(t *testing.T) { + p := Process{ + Concurrency: 1, + Connector: connector, + Playbook: conf, + ColorWriter: executor.NewColorizedWriter(os.Stdout, "", "", "", nil), + Only: []string{"root only single line with var"}, + } + + outWriter := &bytes.Buffer{} + log.SetOutput(io.MultiWriter(outWriter, os.Stderr)) + res, err := p.Run(ctx, "task1", testingHostAndPort) + require.NoError(t, err) + assert.Equal(t, 1, res.Commands) + assert.Equal(t, 1, res.Hosts) + assert.Contains(t, outWriter.String(), " > sudo sh -c 'vvv=123 && echo var=$vvv'") + assert.Contains(t, outWriter.String(), " > var=123") + }) + t.Run("multi line script", func(t *testing.T) { p := Process{ Concurrency: 1, diff --git a/pkg/runner/testdata/conf.yml b/pkg/runner/testdata/conf.yml index 0d1be1b0..51757bae 100644 --- a/pkg/runner/testdata/conf.yml +++ b/pkg/runner/testdata/conf.yml @@ -71,6 +71,11 @@ tasks: script: ls -l /etc options: {no_auto: true, sudo: true} + + - name: root only single line with var + script: vvv=123 && echo var=$vvv + options: {no_auto: true, sudo: true} + - name: root only copy single file copy: {src: testdata/conf.yml, dst: /srv/conf.yml} options: {no_auto: true, sudo: true}