mirror of
https://github.com/aquasecurity/kube-bench.git
synced 2024-11-25 17:38:21 +00:00
b942ed3f0b
Suppress the file not found error only when we have audit or auditEnv is defined and they have valid output captured. As, we already have output from audit command. So we can proceed for our tests even though we didnt find config file. file not found error: `failed to run: "/test/config.yaml", output: "/bin/sh: line 1: /test/config.yaml: No such file or directory\n", error: exit status 127` Resolve: #1364
246 lines
5.6 KiB
Go
246 lines
5.6 KiB
Go
// Copyright © 2017-2020 Aqua Security Software Ltd. <info@aquasec.com>
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package check
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestCheck_Run(t *testing.T) {
|
|
type TestCase struct {
|
|
name string
|
|
check Check
|
|
Expected State
|
|
}
|
|
|
|
testCases := []TestCase{
|
|
{name: "Manual check should WARN", check: Check{Type: MANUAL}, Expected: WARN},
|
|
{name: "Skip check should INFO", check: Check{Type: "skip"}, Expected: INFO},
|
|
{name: "Unscored check (with no type) should WARN on failure", check: Check{Scored: false}, Expected: WARN},
|
|
{
|
|
name: "Unscored check that pass should PASS",
|
|
check: Check{
|
|
Scored: false,
|
|
Audit: "echo hello",
|
|
Tests: &tests{TestItems: []*testItem{{
|
|
Flag: "hello",
|
|
Set: true,
|
|
}}},
|
|
},
|
|
Expected: PASS,
|
|
},
|
|
|
|
{name: "Check with no tests should WARN", check: Check{Scored: true}, Expected: WARN},
|
|
{name: "Scored check with empty tests should FAIL", check: Check{Scored: true, Tests: &tests{}}, Expected: FAIL},
|
|
{
|
|
name: "Scored check that doesn't pass should FAIL",
|
|
check: Check{
|
|
Scored: true,
|
|
Audit: "echo hello",
|
|
Tests: &tests{TestItems: []*testItem{{
|
|
Flag: "hello",
|
|
Set: false,
|
|
}}},
|
|
},
|
|
Expected: FAIL,
|
|
},
|
|
{
|
|
name: "Scored checks that pass should PASS",
|
|
check: Check{
|
|
Scored: true,
|
|
Audit: "echo hello",
|
|
Tests: &tests{TestItems: []*testItem{{
|
|
Flag: "hello",
|
|
Set: true,
|
|
}}},
|
|
},
|
|
Expected: PASS,
|
|
},
|
|
{
|
|
name: "Scored checks that pass should PASS when config file is not present",
|
|
check: Check{
|
|
Scored: true,
|
|
Audit: "echo hello",
|
|
AuditConfig: "/test/config.yaml",
|
|
Tests: &tests{TestItems: []*testItem{{
|
|
Flag: "hello",
|
|
Set: true,
|
|
}}},
|
|
},
|
|
Expected: PASS,
|
|
},
|
|
{
|
|
name: "Scored checks that pass should FAIL when config file is not present",
|
|
check: Check{
|
|
Scored: true,
|
|
AuditConfig: "/test/config.yaml",
|
|
Tests: &tests{TestItems: []*testItem{{
|
|
Flag: "hello",
|
|
Set: true,
|
|
}}},
|
|
},
|
|
Expected: FAIL,
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
testCase.check.run()
|
|
if testCase.check.State != testCase.Expected {
|
|
t.Errorf("expected %s, actual %s", testCase.Expected, testCase.check.State)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCheckAuditEnv(t *testing.T) {
|
|
passingCases := []*Check{
|
|
controls.Groups[2].Checks[0],
|
|
controls.Groups[2].Checks[2],
|
|
controls.Groups[2].Checks[3],
|
|
controls.Groups[2].Checks[4],
|
|
}
|
|
|
|
failingCases := []*Check{
|
|
controls.Groups[2].Checks[1],
|
|
controls.Groups[2].Checks[5],
|
|
controls.Groups[2].Checks[6],
|
|
}
|
|
|
|
for _, c := range passingCases {
|
|
t.Run(c.Text, func(t *testing.T) {
|
|
c.run()
|
|
if c.State != "PASS" {
|
|
t.Errorf("Should PASS, got: %v", c.State)
|
|
}
|
|
})
|
|
}
|
|
|
|
for _, c := range failingCases {
|
|
t.Run(c.Text, func(t *testing.T) {
|
|
c.run()
|
|
if c.State != "FAIL" {
|
|
t.Errorf("Should FAIL, got: %v", c.State)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCheckAuditConfig(t *testing.T) {
|
|
passingCases := []*Check{
|
|
controls.Groups[1].Checks[0],
|
|
controls.Groups[1].Checks[3],
|
|
controls.Groups[1].Checks[5],
|
|
controls.Groups[1].Checks[7],
|
|
controls.Groups[1].Checks[9],
|
|
controls.Groups[1].Checks[15],
|
|
}
|
|
|
|
failingCases := []*Check{
|
|
controls.Groups[1].Checks[1],
|
|
controls.Groups[1].Checks[2],
|
|
controls.Groups[1].Checks[4],
|
|
controls.Groups[1].Checks[6],
|
|
controls.Groups[1].Checks[8],
|
|
controls.Groups[1].Checks[10],
|
|
controls.Groups[1].Checks[11],
|
|
controls.Groups[1].Checks[12],
|
|
controls.Groups[1].Checks[13],
|
|
controls.Groups[1].Checks[14],
|
|
controls.Groups[1].Checks[16],
|
|
}
|
|
|
|
for _, c := range passingCases {
|
|
t.Run(c.Text, func(t *testing.T) {
|
|
c.run()
|
|
if c.State != "PASS" {
|
|
t.Errorf("Should PASS, got: %v", c.State)
|
|
}
|
|
})
|
|
}
|
|
|
|
for _, c := range failingCases {
|
|
t.Run(c.Text, func(t *testing.T) {
|
|
c.run()
|
|
if c.State != "FAIL" {
|
|
t.Errorf("Should FAIL, got: %v", c.State)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
})
|
|
}
|
|
}
|