diff --git a/changes/24470-bash b/changes/24470-bash new file mode 100644 index 000000000000..7f856b78a8d4 --- /dev/null +++ b/changes/24470-bash @@ -0,0 +1 @@ +* Added bash interpreter support for script execution diff --git a/cmd/fleetctl/scripts_test.go b/cmd/fleetctl/scripts_test.go index 05ef4b39fdac..e20f0b7f8bf8 100644 --- a/cmd/fleetctl/scripts_test.go +++ b/cmd/fleetctl/scripts_test.go @@ -112,12 +112,12 @@ hello world { name: "invalid hashbang", scriptPath: func() string { return writeTmpScriptContents(t, "#! /foo/bar", ".sh") }, - expectErrMsg: `Interpreter not supported. Shell scripts must run in "#!/bin/sh" or "#!/bin/zsh."`, + expectErrMsg: `Interpreter not supported. Shell scripts must run in "#!/bin/sh", "#!/bin/bash", or "#!/bin/zsh."`, }, { name: "unsupported hashbang", scriptPath: func() string { return writeTmpScriptContents(t, "#!/bin/ksh", ".sh") }, - expectErrMsg: `Interpreter not supported. Shell scripts must run in "#!/bin/sh" or "#!/bin/zsh."`, + expectErrMsg: `Interpreter not supported. Shell scripts must run in "#!/bin/sh", "#!/bin/bash", or "#!/bin/zsh."`, }, { name: "posix shell hashbang", diff --git a/frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/ScriptUploader.tsx b/frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/ScriptUploader.tsx index ea034a7a09e8..607ae6e12abe 100644 --- a/frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/ScriptUploader.tsx +++ b/frontend/pages/ManageControlsPage/Scripts/components/ScriptUploader/ScriptUploader.tsx @@ -45,7 +45,7 @@ const ScriptPackageUploader = ({ className={baseClass} graphicName={["file-sh", "file-ps1"]} message="Shell (.sh) for macOS and Linux or PowerShell (.ps1) for Windows" - additionalInfo="Script will run with “#!/bin/sh” or “#!/bin/zsh” on macOS and Linux." + additionalInfo="Script will run with “#!/bin/sh”, “#!/bin/zsh”, or “#!/bin/bash” on macOS and Linux." accept=".sh,.ps1" onFileUpload={onUploadFile} isLoading={showLoading} diff --git a/orbit/pkg/scripts/exec_nonwindows_test.go b/orbit/pkg/scripts/exec_nonwindows_test.go index a7997ebc8578..d795a9e6635e 100644 --- a/orbit/pkg/scripts/exec_nonwindows_test.go +++ b/orbit/pkg/scripts/exec_nonwindows_test.go @@ -19,8 +19,10 @@ import ( func TestExecCmdNonWindows(t *testing.T) { zshPath := "/bin/zsh" + bashPath := "/bin/bash" if runtime.GOOS == "linux" { zshPath = "/usr/bin/zsh" + bashPath = "/usr/bin/bash" } tests := []struct { @@ -40,6 +42,11 @@ func TestExecCmdNonWindows(t *testing.T) { contents: "#!/bin/sh\n[ -z \"$ZSH_VERSION\" ] && echo 1", output: "1", }, + { + name: "bash shebang", + contents: "#!" + bashPath + "\n[ -z \"$ZSH_VERSION\" ] && echo 1", + output: "1", + }, { name: "zsh shebang", contents: "#!" + zshPath + "\n[ -n \"$ZSH_VERSION\" ] && echo 1", diff --git a/server/fleet/scripts.go b/server/fleet/scripts.go index 1f1ebb915788..eddc1b0b193e 100644 --- a/server/fleet/scripts.go +++ b/server/fleet/scripts.go @@ -317,8 +317,8 @@ const ( // anchored, so that it matches to the end of the line var ( - scriptHashbangValidation = regexp.MustCompile(`^#!\s*(:?/usr)?/bin/z?sh(?:\s*|\s+.*)$`) - ErrUnsupportedInterpreter = errors.New(`Interpreter not supported. Shell scripts must run in "#!/bin/sh" or "#!/bin/zsh."`) + scriptHashbangValidation = regexp.MustCompile(`^#!\s*(:?/usr)?/bin/(ba|z)?sh(?:\s*|\s+.*)$`) + ErrUnsupportedInterpreter = errors.New(`Interpreter not supported. Shell scripts must run in "#!/bin/sh", "#!/bin/bash", or "#!/bin/zsh."`) ) // ValidateShebang validates if we support a script, and whether we @@ -327,7 +327,7 @@ func ValidateShebang(s string) (directExecute bool, err error) { if strings.HasPrefix(s, "#!") { // read the first line in a portable way s := bufio.NewScanner(strings.NewReader(s)) - // if a hashbang is present, it can only be `/bin/sh` or `(/usr)/bin/zsh` for now + // if a hashbang is present, it can only be `(/usr)/bin/sh`, `(/usr)/bin/bash`, `(/usr)/bin/zsh` for now if s.Scan() && !scriptHashbangValidation.MatchString(s.Text()) { return false, ErrUnsupportedInterpreter } diff --git a/server/fleet/scripts_test.go b/server/fleet/scripts_test.go index f8e92fdcee60..ee062816920f 100644 --- a/server/fleet/scripts_test.go +++ b/server/fleet/scripts_test.go @@ -81,6 +81,11 @@ func TestValidateShebang(t *testing.T) { contents: "#!/bin/zsh\necho hi", directExecute: true, }, + { + name: "bash shebang", + contents: "#!/bin/bash\necho hi", + directExecute: true, + }, { name: "zsh shebang with args", contents: "#!/bin/zsh -x\necho hi", @@ -143,7 +148,7 @@ func TestValidateHostScriptContents(t *testing.T) { }, { name: "unsupported interpreter", - script: "#!/bin/bash\necho 'hello'", + script: "#!/bin/ksh\necho 'hello'", wantErr: ErrUnsupportedInterpreter, }, { @@ -151,6 +156,16 @@ func TestValidateHostScriptContents(t *testing.T) { script: "#!/bin/sh\necho 'hello'", wantErr: nil, }, + { + name: "valid bash script", + script: "#!/bin/bash\necho 'hello'", + wantErr: nil, + }, + { + name: "valid bash script", + script: "#!/usr/bin/bash\necho 'hello'", + wantErr: nil, + }, { name: "valid zsh script", script: "#!/bin/zsh\necho 'hello'", diff --git a/server/service/scripts_test.go b/server/service/scripts_test.go index 91e711c584ee..505119240040 100644 --- a/server/service/scripts_test.go +++ b/server/service/scripts_test.go @@ -313,12 +313,15 @@ func TestHostRunScript(t *testing.T) { {"invalid utf8", "\xff\xfa", "Wrong data format."}, {"valid without hashbang", "echo 'a'", ""}, {"valid with posix hashbang", "#!/bin/sh\necho 'a'", ""}, + {"valid with usr bash hashbang", "#!/usr/bin/bash\necho 'a'", ""}, + {"valid with bash hashbang", "#!/bin/bash\necho 'a'", ""}, + {"valid with bash hashbang and arguments", "#!/bin/bash -x\necho 'a'", ""}, {"valid with usr zsh hashbang", "#!/usr/bin/zsh\necho 'a'", ""}, {"valid with zsh hashbang", "#!/bin/zsh\necho 'a'", ""}, {"valid with zsh hashbang and arguments", "#!/bin/zsh -x\necho 'a'", ""}, {"valid with hashbang and spacing", "#! /bin/sh \necho 'a'", ""}, {"valid with hashbang and Windows newline", "#! /bin/sh \r\necho 'a'", ""}, - {"invalid hashbang", "#!/bin/bash\necho 'a'", "Interpreter not supported."}, + {"invalid hashbang", "#!/bin/ksh\necho 'a'", "Interpreter not supported."}, } ctx = viewer.NewContext(ctx, viewer.Viewer{User: test.UserAdmin})