Skip to content

Commit

Permalink
Merge pull request #108 from aquasecurity/run-shell-scripts
Browse files Browse the repository at this point in the history
Add shell script support
  • Loading branch information
lizrice authored Nov 23, 2020
2 parents f2b98ad + dd3ad04 commit dfdc30c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
28 changes: 27 additions & 1 deletion check/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package check

import (
"bytes"
"fmt"
"os/exec"
"strings"
Expand All @@ -38,7 +39,8 @@ type Audit string
// Execute method called by the main logic to execute the Audit's Execute type.
func (audit Audit) Execute(customConfig ...interface{}) (result string, errMessage string, state State) {

res, err := exec.Command("sh", "-c", string(audit)).CombinedOutput()
res, err := runAudit(string(audit))

// Errors mean the audit command failed, but that might be what we expect
// for example, if we grep for something that is not found, there is a non-zero exit code
// It is a problem if we can't find one of the audit commands to execute, but we deal
Expand Down Expand Up @@ -207,6 +209,30 @@ func (c *Check) Run(definedConstraints map[string][]string) {
}
}

func runAudit(audit string) (output string, err error) {
var out bytes.Buffer

audit = strings.TrimSpace(audit)
if len(audit) == 0 {
return output, err
}

cmd := exec.Command("/bin/sh")
cmd.Stdin = strings.NewReader(audit)
cmd.Stdout = &out
cmd.Stderr = &out
err = cmd.Run()
output = out.String()

if err != nil {
err = fmt.Errorf("failed to run: %q, output: %q, error: %s", audit, output, err)
} else {
glog.V(3).Infof("Command %q\n - Output:\n %q", audit, output)

}
return output, err
}

func runAuditCommands(c BaseCheck) (output, errMessage string, state State) {

// If check type is manual, force result to WARN.
Expand Down
66 changes: 64 additions & 2 deletions check/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,68 @@ func TestGetFirstValidSubCheck(t *testing.T) {
}
}

func Test_runAudit(t *testing.T) {
type args struct {
audit string
output string
}
tests := []struct {
name string
args args
errMsg string
output string
}{
{
name: "run success",
args: args{
audit: "echo 'hello world'",
},
errMsg: "",
output: "hello world\n",
},
{
name: "run multiple lines script",
args: args{
audit: `
hello() {
echo "hello world"
}
hello
`,
},
errMsg: "",
output: "hello world\n",
},
{
name: "run failed",
args: args{
audit: "unknown_command",
},
errMsg: "failed to run: \"unknown_command\", output: \"/bin/sh: ",
output: "not found\n",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var errMsg string
output, err := runAudit(tt.args.audit)
if err != nil {
errMsg = err.Error()
}
if errMsg != "" && !strings.Contains(errMsg, tt.errMsg) {
t.Errorf("name %s errMsg = %q, want %q", tt.name, errMsg, tt.errMsg)
}
if errMsg == "" && output != tt.output {
t.Errorf("name %s output = %q, want %q", tt.name, output, tt.output)
}
if errMsg != "" && !strings.Contains(output, tt.output) {
t.Errorf("name %s output = %q, want %q", tt.name, output, tt.output)
}
})
}
}

func TestRunAuditCommands(t *testing.T) {

cases := []struct {
Expand All @@ -240,7 +302,7 @@ func TestRunAuditCommands(t *testing.T) {
// If the audit command can't be run, we eventually report FAIL but this is done in
// (c *Check) Run() based on the final output
b: BaseCheck{auditer: Audit("anything")},
s: "", err: true, o: "sh: 1: anything: not found",
s: "", err: true, o: "/bin/sh: 1: anything: not found",
}, {
// 3
b: BaseCheck{auditer: Audit("echo hello")},
Expand All @@ -262,7 +324,7 @@ func TestRunAuditCommands(t *testing.T) {
// Like in test #2 the final state will be fail, but currently in runAuditCommands
// is just an empty string
b: BaseCheck{auditer: Audit("echo $(ls . | grep 'bench') | anything")},
s: "", err: true, o: "sh: 1: anything: not found",
s: "", err: true, o: "/bin/sh: 1: anything: not found",
},
}

Expand Down

0 comments on commit dfdc30c

Please sign in to comment.