diff --git a/core/pkg/fixhandler/fixhandler.go b/core/pkg/fixhandler/fixhandler.go index d0e8d3ff..578a1812 100644 --- a/core/pkg/fixhandler/fixhandler.go +++ b/core/pkg/fixhandler/fixhandler.go @@ -243,6 +243,7 @@ func (h *FixHandler) getFilePathAndIndex(filePathWithIndex string) (filePath str } func ApplyFixToContent(ctx context.Context, yamlAsString, yamlExpression string) (fixedString string, err error) { + yamlAsString = sanitizeYaml(yamlAsString) newline := determineNewlineSeparator(yamlAsString) yamlLines := strings.Split(yamlAsString, newline) @@ -264,6 +265,7 @@ func ApplyFixToContent(ctx context.Context, yamlAsString, yamlExpression string) fixedYamlLines := getFixedYamlLines(yamlLines, fixInfo, newline) fixedString = getStringFromSlice(fixedYamlLines, newline) + fixedString = revertSanitizeYaml(fixedString) return fixedString, nil } @@ -368,3 +370,28 @@ func determineNewlineSeparator(contents string) string { return unixNewline } } + +// sanitizeYaml receives a YAML file as a string, sanitizes it and returns the result +// +// Callers should remember to call the corresponding revertSanitizeYaml function. +// +// It applies the following sanitization: +// +// - 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 fileAsString[:3] == "---" { + fileAsString = "# " + fileAsString + } + return fileAsString +} + +// revertSanitizeYaml receives a sanitized YAML file as a string and reverts the applied sanitization +// +// For sanitization details, refer to the sanitizeYaml() function. +func revertSanitizeYaml(fixedYamlString string) string { + if fixedYamlString[:5] == "# ---" { + fixedYamlString = fixedYamlString[2:] + } + return fixedYamlString +} diff --git a/core/pkg/fixhandler/fixhandler_test.go b/core/pkg/fixhandler/fixhandler_test.go index 81d049f1..d598dd83 100644 --- a/core/pkg/fixhandler/fixhandler_test.go +++ b/core/pkg/fixhandler/fixhandler_test.go @@ -101,6 +101,13 @@ func getTestCases() []indentationTestCase { "inserts/tc-11-01-expected.yaml", }, + // Starts with --- + { + "inserts/tc-12-00-begin-with-document-separator.yaml", + "select(di==0).spec.containers[0].securityContext.allowPrivilegeEscalation |= false", + "inserts/tc-12-01-expected.yaml", + }, + // Removal Scenarios { "removals/tc-01-00-input.yaml", @@ -118,10 +125,10 @@ func getTestCases() []indentationTestCase { "removals/tc-03-01-expected.yaml", }, { - "removes/tc-04-00-input.yaml", + "removals/tc-04-00-input.yaml", `del(select(di==0).spec.containers[0].securityContext) | del(select(di==1).spec.containers[1])`, - "removes/tc-04-01-expected.yaml", + "removals/tc-04-01-expected.yaml", }, // Replace Scenarios @@ -162,6 +169,12 @@ func getTestCases() []indentationTestCase { select(di==0).spec.securityContext.runAsRoot |= false`, "hybrids/tc-04-01-expected.yaml", }, + { + "hybrids/tc-05-00-input-leading-doc-separator.yaml", + `del(select(di==0).spec.containers[0].securityContext) | + select(di==0).spec.securityContext.runAsRoot |= false`, + "hybrids/tc-05-01-expected.yaml", + }, } return indentationTestCases @@ -169,20 +182,28 @@ func getTestCases() []indentationTestCase { func TestApplyFixKeepsFormatting(t *testing.T) { testCases := getTestCases() + getTestDataPath := func(filename string) string { + currentFile := "testdata/" + filename + return filepath.Join(testutils.CurrentDir(), currentFile) + } for _, tc := range testCases { t.Run(tc.inputFile, func(t *testing.T) { - getTestDataPath := func(filename string) string { - currentFile := "testdata/" + filename - return filepath.Join(testutils.CurrentDir(), currentFile) + inputFilename := getTestDataPath(tc.inputFile) + input, err := os.ReadFile(inputFilename) + if err != nil { + t.Fatalf(`Unable to open file %s due to: %v`, inputFilename, err) + } + expectedFilename := getTestDataPath(tc.expectedFile) + wantRaw, err := os.ReadFile(expectedFilename) + if err != nil { + t.Fatalf(`Unable to open file %s due to: %v`, expectedFilename, err) } - - input, _ := os.ReadFile(getTestDataPath(tc.inputFile)) - wantRaw, _ := os.ReadFile(getTestDataPath(tc.expectedFile)) want := string(wantRaw) expression := tc.yamlExpression - got, _ := ApplyFixToContent(context.TODO(), string(input), expression) + fileAsString := string(input) + got, _ := ApplyFixToContent(context.TODO(), fileAsString, expression) assert.Equalf( t, want, got, diff --git a/core/pkg/fixhandler/testdata/hybrids/tc-05-00-input-leading-doc-separator.yaml b/core/pkg/fixhandler/testdata/hybrids/tc-05-00-input-leading-doc-separator.yaml new file mode 100644 index 00000000..9a6bc1bf --- /dev/null +++ b/core/pkg/fixhandler/testdata/hybrids/tc-05-00-input-leading-doc-separator.yaml @@ -0,0 +1,22 @@ +# Fix to Apply: +# REMOVE: +# "del(select(di==0).spec.containers[0].securityContext)" + +# INSERT: +# select(di==0).spec.securityContext.runAsRoot: false + + +--- +apiVersion: v1 +kind: Pod +metadata: + name: insert_to_mapping_node_1 + +spec: + containers: + - name: nginx_container + + image: nginx + + securityContext: + runAsRoot: true diff --git a/core/pkg/fixhandler/testdata/hybrids/tc-05-01-expected.yaml b/core/pkg/fixhandler/testdata/hybrids/tc-05-01-expected.yaml new file mode 100644 index 00000000..5beb28d4 --- /dev/null +++ b/core/pkg/fixhandler/testdata/hybrids/tc-05-01-expected.yaml @@ -0,0 +1,22 @@ +# Fix to Apply: +# REMOVE: +# "del(select(di==0).spec.containers[0].securityContext)" + +# INSERT: +# select(di==0).spec.securityContext.runAsRoot: false + + +--- +apiVersion: v1 +kind: Pod +metadata: + name: insert_to_mapping_node_1 + +spec: + containers: + - name: nginx_container + + image: nginx + securityContext: + runAsRoot: false + diff --git a/core/pkg/fixhandler/testdata/inserts/tc-12-00-begin-with-document-separator.yaml b/core/pkg/fixhandler/testdata/inserts/tc-12-00-begin-with-document-separator.yaml new file mode 100644 index 00000000..61d8bee3 --- /dev/null +++ b/core/pkg/fixhandler/testdata/inserts/tc-12-00-begin-with-document-separator.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: Pod +metadata: + name: begin-with-document-separator + +spec: + containers: + - name: nginx_container + image: nginx diff --git a/core/pkg/fixhandler/testdata/inserts/tc-12-01-expected.yaml b/core/pkg/fixhandler/testdata/inserts/tc-12-01-expected.yaml new file mode 100644 index 00000000..8116502f --- /dev/null +++ b/core/pkg/fixhandler/testdata/inserts/tc-12-01-expected.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: v1 +kind: Pod +metadata: + name: begin-with-document-separator + +spec: + containers: + - name: nginx_container + image: nginx + securityContext: + allowPrivilegeEscalation: false