Merge pull request #1516 from mohaidoss/tests/core-pkg-fixhandler

Bug Fix and Test Addition for sanitizeYaml and revertSanitizeYaml Functions
This commit is contained in:
Matthias Bertschy
2023-11-25 22:31:39 +01:00
committed by GitHub
2 changed files with 395 additions and 1 deletions
+10 -1
View File
@@ -8,6 +8,7 @@ import (
"os"
"path"
"path/filepath"
"sort"
"strconv"
"strings"
@@ -313,7 +314,7 @@ func reduceYamlExpressions(resource *ResourceFixInfo) string {
for expr := range resource.YamlExpressions {
expressions = append(expressions, expr)
}
sort.Strings(expressions)
return strings.Join(expressions, " | ")
}
@@ -378,6 +379,10 @@ func determineNewlineSeparator(contents string) string {
// - Since `yaml/v3` fails to serialize documents starting with a document
// separator, we comment it out to be compatible.
func sanitizeYaml(fileAsString string) string {
if len(fileAsString) < 3 {
return fileAsString
}
if fileAsString[:3] == "---" {
fileAsString = "# " + fileAsString
}
@@ -388,6 +393,10 @@ func sanitizeYaml(fileAsString string) string {
//
// For sanitization details, refer to the sanitizeYaml() function.
func revertSanitizeYaml(fixedYamlString string) string {
if len(fixedYamlString) < 3 {
return fixedYamlString
}
if fixedYamlString[:5] == "# ---" {
fixedYamlString = fixedYamlString[2:]
}
+385
View File
@@ -6,6 +6,7 @@ import (
"path/filepath"
"testing"
"github.com/armosec/armoapi-go/armotypes"
logger "github.com/kubescape/go-logger"
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
"github.com/kubescape/kubescape/v3/internal/testutils"
@@ -266,3 +267,387 @@ func Test_fixPathToValidYamlExpression(t *testing.T) {
})
}
}
func TestJoinStrings(t *testing.T) {
tests := []struct {
name string
args []string
want string
}{
{
name: "nil array",
args: nil,
want: "",
},
{
name: "empty array",
args: []string{},
want: "",
},
{
name: "single element",
args: []string{"a"},
want: "a",
},
{
name: "two elements",
args: []string{"a", "b"},
want: "ab",
},
{
name: "three elements",
args: []string{"a", "b", "c"},
want: "abc",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := joinStrings(tt.args...); got != tt.want {
t.Errorf("joinStrings() = %v, want %v", got, tt.want)
}
})
}
}
func TestGetFileString(t *testing.T) {
type args struct {
filePath string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "file not found",
args: args{
filePath: "notfound.yaml",
},
want: "",
wantErr: true,
},
{
name: "file found",
args: args{
filePath: "testdata/inserts/tc-01-00-input-mapping-insert-mapping.yaml",
},
want: `# Fix to Apply:
# "select(di==0).spec.containers[0].securityContext.allowPrivilegeEscalation |= false"
apiVersion: v1
kind: Pod
metadata:
name: insert_to_mapping_node_1
spec:
containers:
- name: nginx_container
image: nginx
`,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := GetFileString(tt.args.filePath)
if (err != nil) != tt.wantErr {
t.Errorf("getFileString() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want && !tt.wantErr {
t.Errorf("getFileString() got = %v, want %v", got, tt.want)
}
})
}
}
func TestDetermineNewlineSeparator(t *testing.T) {
type args struct {
fileString string
}
tests := []struct {
name string
args args
want string
}{
{
name: "empty",
args: args{
fileString: "",
},
want: "\n",
},
{
name: "windows newline",
args: args{
fileString: "a\r\nb\r\nc\r\n",
},
want: "\r\n",
},
{
name: "linux newline",
args: args{
fileString: "a\nb\nc\n",
},
want: "\n",
},
{
name: "oldmac newline",
args: args{
fileString: "a\rb\rc\r",
},
want: "\n",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := determineNewlineSeparator(tt.args.fileString); got != tt.want {
t.Errorf("determineNewlineSeparator() = %v, want %v", got, tt.want)
}
})
}
}
func TestSanitizeYaml(t *testing.T) {
type args struct {
fileString string
}
tests := []struct {
name string
args args
want string
}{
{
name: "empty yaml",
args: args{
fileString: "",
},
want: "",
},
{
name: "empty yaml with two characters",
args: args{
fileString: "##",
},
want: "##",
},
{
name: "yaml/v3",
args: args{
fileString: `apiVersion: v1
kind: Pod
metadata:
name: insert_to_mapping_node_1
`,
},
want: `apiVersion: v1
kind: Pod
metadata:
name: insert_to_mapping_node_1
`,
},
{
name: "yaml/v2",
args: args{
fileString: `apiVersion: v1
kind: Pod
metadata:
name: insert_to_mapping_node_1
---
apiVersion: v1
kind: Pod
metadata:
name: insert_to_mapping_node_2
`,
},
want: `apiVersion: v1
kind: Pod
metadata:
name: insert_to_mapping_node_1
---
apiVersion: v1
kind: Pod
metadata:
name: insert_to_mapping_node_2
`,
},
{
name: "yaml/v1",
args: args{
fileString: `---
apiVersion: v1
kind: Pod
metadata:
name: insert_to_mapping_node_1
`,
},
want: `# ---
apiVersion: v1
kind: Pod
metadata:
name: insert_to_mapping_node_1
`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := sanitizeYaml(tt.args.fileString); got != tt.want {
t.Errorf("sanitizeYaml() = %v, want %v", got, tt.want)
}
})
}
}
func TestReduceYamlExpressions(t *testing.T) {
type args struct {
yamlExpressions []string
}
tests := []struct {
name string
args args
want string
}{
{
name: "empty",
args: args{
yamlExpressions: []string{},
},
want: "",
},
{
name: "one expression",
args: args{
yamlExpressions: []string{
"select(di==0).spec.containers[0].securityContext.allowPrivilegeEscalation |= false",
},
},
want: "select(di==0).spec.containers[0].securityContext.allowPrivilegeEscalation |= false",
},
{
name: "two expressions",
args: args{
yamlExpressions: []string{
"select(di==0).spec.containers[0].securityContext.allowPrivilegeEscalation |= false",
"select(di==0).spec.containers[0].securityContext.capabilities.drop += [\"NET_RAW\"]",
},
},
want: "select(di==0).spec.containers[0].securityContext.allowPrivilegeEscalation |= false | select(di==0).spec.containers[0].securityContext.capabilities.drop += [\"NET_RAW\"]",
},
{
name: "Duplicate expressions",
args: args{
yamlExpressions: []string{
"select(di==0).spec.containers[0].securityContext.allowPrivilegeEscalation |= false",
"select(di==0).spec.containers[0].securityContext.capabilities.drop += [\"NET_RAW\"]",
"select(di==0).spec.containers[0].securityContext.allowPrivilegeEscalation |= false",
},
},
want: "select(di==0).spec.containers[0].securityContext.allowPrivilegeEscalation |= false | select(di==0).spec.containers[0].securityContext.capabilities.drop += [\"NET_RAW\"]",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource := &ResourceFixInfo{}
resource.YamlExpressions = make(map[string]armotypes.FixPath)
for _, yamlExpression := range tt.args.yamlExpressions {
resource.YamlExpressions[yamlExpression] = armotypes.FixPath{}
}
got := reduceYamlExpressions(resource)
assert.Equal(t, tt.want, got)
})
}
}
func TestGetLocalPath(t *testing.T) {
type args struct {
report *reporthandlingv2.PostureReport
}
tests := []struct {
name string
args args
want string
}{
{
name: "empty report",
args: args{
report: &reporthandlingv2.PostureReport{},
},
want: "",
},
{
name: "No scan metadata",
args: args{
report: &reporthandlingv2.PostureReport{
Metadata: reporthandlingv2.Metadata{
ScanMetadata: reporthandlingv2.ScanMetadata{},
},
},
},
want: "",
},
{
name: "Scan target GitLocal",
args: args{
report: &reporthandlingv2.PostureReport{
Metadata: reporthandlingv2.Metadata{
ScanMetadata: reporthandlingv2.ScanMetadata{
ScanningTarget: reporthandlingv2.ScanningTarget(3),
},
ContextMetadata: reporthandlingv2.ContextMetadata{
RepoContextMetadata: &reporthandlingv2.RepoContextMetadata{
LocalRootPath: "/tmp",
},
},
},
},
},
want: "/tmp",
},
{
name: "Scan target Directory",
args: args{
report: &reporthandlingv2.PostureReport{
Metadata: reporthandlingv2.Metadata{
ScanMetadata: reporthandlingv2.ScanMetadata{
ScanningTarget: reporthandlingv2.ScanningTarget(2),
},
ContextMetadata: reporthandlingv2.ContextMetadata{
DirectoryContextMetadata: &reporthandlingv2.DirectoryContextMetadata{
BasePath: "/tmp",
},
},
},
},
},
},
{
name: "Scan target File",
args: args{
report: &reporthandlingv2.PostureReport{
Metadata: reporthandlingv2.Metadata{
ScanMetadata: reporthandlingv2.ScanMetadata{
ScanningTarget: reporthandlingv2.ScanningTarget(1),
},
ContextMetadata: reporthandlingv2.ContextMetadata{
FileContextMetadata: &reporthandlingv2.FileContextMetadata{
FilePath: "/tmp/target.yaml",
},
},
},
},
},
want: "/tmp",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getLocalPath(tt.args.report); got != tt.want {
t.Errorf("getLocalPath() = %v, want %v", got, tt.want)
}
})
}
}