Repository: aquasecurity/kube-bench
Pull request #790 (2020-12-23 14:19:04)

chore: build and push action for ecr and docker
- Remove the publish-ecr file 
- Use the build-push action in publish.yml with docker and ecr.
- Change the name secret for the use in the organization (DOCKER_HUB_USERNAME)
- Build using only platforms: linux/amd64, less time to build it.

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/kube-bench/pull/790?src=pr&el=h1) Report
> Merging [#790](https://codecov.io/gh/aquasecurity/kube-bench/pull/790?src=pr&el=desc) (eb81a55) into [main](https://codecov.io/gh/aquasecurity/kube-bench/commit/b6f619cdcb1f185b8f6b5a27722247a52e0e3911?el=desc) (b6f619c) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/aquasecurity/kube-bench/pull/790/graphs/tree.svg?width=650&height=150&src=pr&token=MVaDEmdgi9)](https://codecov.io/gh/aquasecurity/kube-bench/pull/790?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##             main     #790   +/-   ##
=======================================
  Coverage   67.11%   67.11%           
=======================================
  Files          14       14           
  Lines        1253     1253           
=======================================
  Hits          841      841           
  Misses        359      359           
  Partials       53       53           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/aquasecurity/kube-bench/pull/790?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/aquasecurity/kube-bench/pull/790?src=pr&el=footer). Last update [b6f619c...eb81a55](https://codecov.io/gh/aquasecurity/kube-bench/pull/790?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/.github/workflows/publish-ecr.yml b/.github/workflows/publish-ecr.yml
deleted file mode 100644
index c6014e8..0000000
--- a/.github/workflows/publish-ecr.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-name: Publish-ECR
-on:
-  push:
-    tags:
-      - "v*"
-
-jobs:
-  deploy:
-    name: Publish to Amazon ECR
-    runs-on: ubuntu-18.04
-    steps:
-      - name: Configure AWS credentials
-        uses: aws-actions/configure-aws-credentials@v1
-        with:
-          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
-          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
-          aws-region: us-east-1
-      - name: Checkout code
-        uses: actions/checkout@v2
-      - name: Install AWS Cli 2.0
-        run: |
-          curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
-          unzip awscliv2.zip
-          sudo ./aws/install
-      - name: Get the version
-        id: vars
-        run: echo ::set-output name=tag::$(echo ${GITHUB_REF:10})
-      - name: Publish to ECR
-        env:
-          IMAGE_TAG: ${{steps.vars.outputs.tag}}
-          REP_NAME: kube-bench
-          ALIAS: aquasecurity
-        run: |
-          aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/$ALIAS
-          docker build -t $REP_NAME:$IMAGE_TAG .
-          docker tag $REP_NAME:$IMAGE_TAG public.ecr.aws/$ALIAS/$REP_NAME:$IMAGE_TAG
-          docker push public.ecr.aws/$ALIAS/$REP_NAME:$IMAGE_TAG
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 7279e6d..02330fe 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -1,8 +1,12 @@
+---
 name: Publish
 on:
   push:
     tags:
       - "v*"
+env:
+  ALIAS: aquasecurity
+  REP: kube-bench
 jobs:
   publish:
     name: Publish
@@ -12,41 +16,50 @@ jobs:
         uses: actions/checkout@v2
       - name: Set up QEMU
         uses: docker/setup-qemu-action@v1
+      - name: Set up Docker Buildx
+        id: buildx
+        uses: docker/setup-buildx-action@v1
       - name: Cache Docker layers
         uses: actions/cache@v2
         with:
           path: /tmp/.buildx-cache
-          key: ${{ runner.os }}-buildx-${{ github.sha }}
+          key: ${{ runner.os }}-buildxarch-${{ github.sha }}
           restore-keys: |
-            ${{ runner.os }}-buildx-
+            ${{ runner.os }}-buildxarch-
       - name: Login to Docker Hub
         uses: docker/login-action@v1
         with:
-          username: ${{ secrets.DOCKER_HUB_USERNAME }}
-          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
-      - name: Set up Docker Buildx
-        id: buildx
-        uses: docker/setup-buildx-action@v1
-      - name: Docker meta
-        id: docker_meta
+          username: ${{ secrets.DOCKERHUB_USER }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      - name: Login to ECR
+        uses: docker/login-action@v1
+        with:
+          registry: public.ecr.aws
+          username: ${{ secrets.ECR_ACCESS_KEY_ID }}
+          password: ${{ secrets.ECR_SECRET_ACCESS_KEY }}
+      - name: Get version
+        id: get_version
         uses: crazy-max/ghaction-docker-meta@v1
         with:
-          images: aquasec/kube-bench
+          images: ${{ env.REP }}
           tag-semver: |
             {{version}}
-      - name: Build and push
+
+      - name: Build and push - Docker/ECR
         id: docker_build
         uses: docker/build-push-action@v2
         with:
-          context: ./
-          file: ./Dockerfile
-          platforms: linux/amd64,linux/arm64,linux/386
+          context: .
+          platforms: linux/amd64
           builder: ${{ steps.buildx.outputs.name }}
           push: true
           tags: |
-            ${{ steps.docker_meta.outputs.tags }}
-          cache-from: type=local,src=/tmp/.buildx-cache
-          cache-to: type=local,dest=/tmp/.buildx-cache
-          labels: ${{ steps.docker_meta.outputs.labels }}
+            ${{ secrets.DOCKERHUB_USER }}/${{ env.REP }}:${{ steps.get_version.outputs.version }}
+            public.ecr.aws/${{ env.ALIAS }}/${{ env.REP }}:${{ steps.get_version.outputs.version }}
+            ${{ secrets.DOCKERHUB_USER }}/${{ env.REP }}:latest
+            public.ecr.aws/${{ env.ALIAS }}/${{ env.REP }}:latest
+          cache-from: type=local,src=/tmp/.buildx-cache/release
+          cache-to: type=local,mode=max,dest=/tmp/.buildx-cache/release
+
       - name: Image digest
         run: echo ${{ steps.docker_build.outputs.digest }}
diff --git a/check/check.go b/check/check.go
index eb24bff..da621d7 100644
--- a/check/check.go
+++ b/check/check.go
@@ -84,7 +84,7 @@ type Check struct {
 	AuditOutput       string `json:"-"`
 	AuditEnvOutput    string `json:"-"`
 	AuditConfigOutput string `json:"-"`
-	DisableEnvTesting bool `json:"-"`
+	DisableEnvTesting bool   `json:"-"`
 }
 
 // Runner wraps the basic Run method.
@@ -220,14 +220,22 @@ func (c *Check) execute() (finalOutput *testOutput, err error) {
 		// Try with the auditOutput first, and if that's not found, try the auditConfigOutput
 		t.auditUsed = AuditCommand
 		result := *(t.execute(c.AuditOutput))
-		if !result.found {
+    
+		// Check for AuditConfigOutput only if AuditConfig is set
+		if !result.flagFound && c.AuditConfig != "" {
+			//t.isConfigSetting = true
 			t.auditUsed = AuditConfig
 			result = *(t.execute(c.AuditConfigOutput))
-			if !result.found && t.Env != "" {
+			if !result.flagFound && t.Env != "" {
 				t.auditUsed = AuditEnv
 				result = *(t.execute(c.AuditEnvOutput))
 			}
 		}
+
+		if !result.flagFound && t.Env != "" {
+			t.auditUsed = AuditEnv
+			result = *(t.execute(c.AuditEnvOutput))
+		}
 		res[i] = result
 		expectedResultArr[i] = res[i].ExpectedResult
 	}
diff --git a/check/data b/check/data
index 4e0b214..fa3c2fe 100644
--- a/check/data
+++ b/check/data
@@ -1,14 +1,15 @@
 ---
 controls:
 id: 1
-text: "Master Checks"
+text: "Test Checks"
 type: "master"
 groups:
 - id: 1.1
-  text: "Kube-apiserver"
+  text: "First Group"
   checks:
     - id: 0
       text: "flag is set"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--allow-privileged"
@@ -16,6 +17,7 @@ groups:
 
     - id: 1
       text: "flag is not set"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--basic-auth"
@@ -23,6 +25,7 @@ groups:
 
     - id: 2
       text: "flag value is set to some value"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--insecure-port"
@@ -33,6 +36,7 @@ groups:
 
     - id: 3
       text: "flag value is greater than or equal some number"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--audit-log-maxage"
@@ -43,6 +47,7 @@ groups:
 
     - id: 4
       text: "flag value is less than some number"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--max-backlog"
@@ -53,6 +58,7 @@ groups:
 
     - id: 5
       text: "flag value does not have some value"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--admission-control"
@@ -63,6 +69,7 @@ groups:
 
     - id: 6
       text: "test AND binary operation"
+      audit: "echo \"Non empty command\""
       tests:
         bin_op: and
         test_items:
@@ -73,6 +80,7 @@ groups:
 
     - id: 7
       text: "test OR binary operation"
+      audit: "echo \"Non empty command\""
       tests:
         bin_op: or
         test_items:
@@ -87,38 +95,29 @@ groups:
 
     - id: 8
       text: "test flag with arbitrary text"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
-        - flag: "644"
+        - flag: "permissions"
           compare:
             op: eq
-            value: "644"
+            value: "SomeValue"
           set: true
 
     - id: 9
       text: "test permissions"
-      audit: "/bin/sh -c 'if test -e $config; then stat -c %a $config; fi'"
+      audit: "/bin/sh -c 'if test -e $config; then stat -c permissions=%a $config; fi'"
       tests:
-        bin_op: or
         test_items:
-        - flag: "644"
+        - flag: "permissions"
           compare:
-            op: eq
+            op: bitmask
             value: "644"
           set: true
-        - flag: "640"
-          compare:
-            op: eq
-            value: "640"
-          set: true
-        - flag: "600"
-          compare:
-            op: eq
-            value: "600"
-          set: true
 
     - id: 10
       text: "flag value includes some value in a comma-separated list, value is last in list"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--admission-control"
@@ -129,6 +128,7 @@ groups:
 
     - id: 11
       text: "flag value includes some value in a comma-separated list, value is first in list"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--admission-control"
@@ -139,6 +139,7 @@ groups:
 
     - id: 12
       text: "flag value includes some value in a comma-separated list, value middle of list"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--admission-control"
@@ -149,6 +150,7 @@ groups:
 
     - id: 13
       text: "flag value includes some value in a comma-separated list, value only one in list"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--admission-control"
@@ -159,6 +161,7 @@ groups:
 
     - id: 14
       text: "check that flag some-arg is set to some-val with ':' separator"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "some-arg"
@@ -169,7 +172,10 @@ groups:
 
     - id: 15
       text: "jsonpath correct value on field"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
+        bin_op: or
         test_items:
           - path: "{.readOnlyPort}"
             compare:
@@ -189,6 +195,8 @@ groups:
 
     - id: 16
       text: "jsonpath correct case-sensitive value on string field"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.stringValue}"
@@ -209,6 +217,8 @@ groups:
 
     - id: 17
       text: "jsonpath correct value on boolean field"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.trueValue}"
@@ -229,6 +239,8 @@ groups:
 
     - id: 18
       text: "jsonpath field absent"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.notARealField}"
@@ -236,6 +248,8 @@ groups:
 
     - id: 19
       text: "jsonpath correct value on nested field"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.authentication.anonymous.enabled}"
@@ -246,6 +260,8 @@ groups:
 
     - id: 20
       text: "yamlpath correct value on field"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.readOnlyPort}"
@@ -256,6 +272,8 @@ groups:
 
     - id: 21
       text: "yamlpath field absent"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.fieldThatIsUnset}"
@@ -263,6 +281,8 @@ groups:
 
     - id: 22
       text: "yamlpath correct value on nested field"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.authentication.anonymous.enabled}"
@@ -273,6 +293,8 @@ groups:
 
     - id: 23
       text: "path on invalid json"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.authentication.anonymous.enabled}"
@@ -283,13 +305,16 @@ groups:
 
     - id: 24
       text: "path with broken expression"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
-          - path: "{.missingClosingBrace"
+          - path: "{.missingClosingBrace}"
             set: true
 
     - id: 25
       text: "yamlpath on invalid yaml"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.authentication.anonymous.enabled}"
@@ -300,6 +325,8 @@ groups:
 
     - id: 26
       text: "check regex op matches"
+      audit: "echo \"Non empty command\""
+      audit_config: "echo \"Non empty command\""
       tests:
         test_items:
           - path: "{.currentMasterVersion}"
@@ -310,6 +337,7 @@ groups:
 
     - id: 27
       text: "check boolean flag with no value"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--peer-client-cert-auth"
@@ -320,6 +348,7 @@ groups:
 
     - id: 28
       text: "check boolean flag with false value"
+      audit: "echo \"Non empty command\""
       tests:
         test_items:
           - flag: "--peer-client-cert-auth"
@@ -587,7 +616,7 @@ groups:
             path: '{.readOnlyPort}'
             set: false
       scored: true
-    - id: 15
+    - id: 16
       text: "parameter and config file don't have same default - parameter has bad value and config is not present - failing"
       audit: "echo '--read-only-port=1'"
       audit_config: "echo ''"


Test patch:
diff --git a/check/test.go b/check/test.go
index 7664cd0..b5abd30 100644
--- a/check/test.go
+++ b/check/test.go
@@ -52,8 +52,8 @@ type AuditUsed string
 
 const (
 	AuditCommand AuditUsed = "auditCommand"
-	AuditConfig AuditUsed = "auditConfig"
-	AuditEnv AuditUsed = "auditEnv"
+	AuditConfig  AuditUsed = "auditConfig"
+	AuditEnv     AuditUsed = "auditEnv"
 )
 
 type testItem struct {
@@ -65,7 +65,7 @@ type testItem struct {
 	Set              bool
 	Compare          compare
 	isMultipleOutput bool
-	auditUsed  AuditUsed
+	auditUsed        AuditUsed
 }
 
 type envTestItem testItem
@@ -79,7 +79,7 @@ type compare struct {
 
 type testOutput struct {
 	testResult     bool
-	found      bool
+	flagFound      bool
 	actualResult   string
 	ExpectedResult string
 }
@@ -178,7 +178,7 @@ func (t envTestItem) findValue(s string) (match bool, value string, err error) {
 		if len(out) > 0 {
 			match = true
 			value = out
-		}else{
+		} else {
 			match = false
 			value = ""
 		}
@@ -221,7 +221,7 @@ func (t testItem) evaluate(s string) *testOutput {
 
 	if t.Set {
 		if match && t.Compare.Op != "" {
-			result.ExpectedResult, result.testResult = compareOp(t.Compare.Op, value, t.Compare.Value)
+			result.ExpectedResult, result.testResult = compareOp(t.Compare.Op, value, t.Compare.Value, t.value())
 		} else {
 			result.ExpectedResult = fmt.Sprintf("'%s' is present", t.value())
 			result.testResult = match
@@ -231,13 +231,14 @@ func (t testItem) evaluate(s string) *testOutput {
 		result.testResult = !match
 	}
 
-	result.found = match
-	glog.V(3).Info(fmt.Sprintf("found %v", result.found))
+	result.flagFound = match
+	glog.V(3).Info(fmt.Sprintf("found %v", result.flagFound))
+
 
 	return result
 }
 
-func compareOp(tCompareOp string, flagVal string, tCompareValue string) (string, bool) {
+func compareOp(tCompareOp string, flagVal string, tCompareValue string, flagName string) (string, bool) {
 
 	expectedResultPattern := ""
 	testResult := false
@@ -266,24 +267,25 @@ func compareOp(tCompareOp string, flagVal string, tCompareValue string) (string,
 	case "gt", "gte", "lt", "lte":
 		a, b, err := toNumeric(flagVal, tCompareValue)
 		if err != nil {
+			expectedResultPattern = "Invalid Number(s) used for comparison: '%s' '%s'"
 			glog.V(1).Infof(fmt.Sprintf("Not numeric value - flag: %q - compareValue: %q %v\n", flagVal, tCompareValue, err))
-			return "Invalid Number(s) used for comparison", false
+			return fmt.Sprintf(expectedResultPattern, flagVal, tCompareValue), false
 		}
 		switch tCompareOp {
 		case "gt":
-			expectedResultPattern = "%s is greater than %s"
+			expectedResultPattern = "'%s' is greater than %s"
 			testResult = a > b
 
 		case "gte":
-			expectedResultPattern = "%s is greater or equal to %s"
+			expectedResultPattern = "'%s' is greater or equal to %s"
 			testResult = a >= b
 
 		case "lt":
-			expectedResultPattern = "%s is lower than %s"
+			expectedResultPattern = "'%s' is lower than %s"
 			testResult = a < b
 
 		case "lte":
-			expectedResultPattern = "%s is lower or equal to %s"
+			expectedResultPattern = "'%s' is lower or equal to %s"
 			testResult = a <= b
 		}
 
@@ -292,11 +294,11 @@ func compareOp(tCompareOp string, flagVal string, tCompareValue string) (string,
 		testResult = strings.Contains(flagVal, tCompareValue)
 
 	case "nothave":
-		expectedResultPattern = " '%s' not have '%s'"
+		expectedResultPattern = "'%s' does not have '%s'"
 		testResult = !strings.Contains(flagVal, tCompareValue)
 
 	case "regex":
-		expectedResultPattern = " '%s' matched by '%s'"
+		expectedResultPattern = "'%s' matched by regex expression '%s'"
 		opRe := regexp.MustCompile(tCompareValue)
 		testResult = opRe.MatchString(flagVal)
 
@@ -307,7 +309,7 @@ func compareOp(tCompareOp string, flagVal string, tCompareValue string) (string,
 		testResult = allElementsValid(s, target)
 
 	case "bitmask":
-		expectedResultPattern = "bitmask '%s' AND '%s'"
+		expectedResultPattern = "%s has permissions " + flagVal + ", expected %s or more restrictive"
 		requested, err := strconv.ParseInt(flagVal, 8, 64)
 		if err != nil {
 			glog.V(1).Infof(fmt.Sprintf("Not numeric value - flag: %q - compareValue: %q %v\n", flagVal, tCompareValue, err))
@@ -324,7 +326,7 @@ func compareOp(tCompareOp string, flagVal string, tCompareValue string) (string,
 		return expectedResultPattern, testResult
 	}
 
-	return fmt.Sprintf(expectedResultPattern, flagVal, tCompareValue), testResult
+	return fmt.Sprintf(expectedResultPattern, flagName, tCompareValue), testResult
 }
 
 func unmarshal(s string, jsonInterface *interface{}) error {
diff --git a/check/test_test.go b/check/test_test.go
index cafc7a2..12879b4 100644
--- a/check/test_test.go
+++ b/check/test_test.go
@@ -48,248 +48,257 @@ func init() {
 func TestTestExecute(t *testing.T) {
 
 	cases := []struct {
-		*Check
-		str       string
-		strConfig string
-		strEnv    string
+		check              *Check
+		str                string
+		strConfig          string
+		expectedTestResult string
+		strEnv             string
 	}{
 		{
-			controls.Groups[0].Checks[0],
-			"2:45 ../kubernetes/kube-apiserver --allow-privileged=false --option1=20,30,40",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[0],
+			str:                "2:45 ../kubernetes/kube-apiserver --allow-privileged=false --option1=20,30,40",
+			strConfig:          "",
+			expectedTestResult: "'--allow-privileged' is present",
 		},
 		{
-			controls.Groups[0].Checks[1],
-			"2:45 ../kubernetes/kube-apiserver --allow-privileged=false",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[1],
+			str:                "2:45 ../kubernetes/kube-apiserver --allow-privileged=false",
+			strConfig:          "",
+			expectedTestResult: "'--basic-auth' is not present",
 		},
 		{
-			controls.Groups[0].Checks[2],
-			"niinai   13617  2635 99 19:26 pts/20   00:03:08 ./kube-apiserver --insecure-port=0 --anonymous-auth",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[2],
+			str:                "niinai   13617  2635 99 19:26 pts/20   00:03:08 ./kube-apiserver --insecure-port=0 --anonymous-auth",
+			strConfig:          "",
+			expectedTestResult: "'--insecure-port' is equal to '0'",
 		},
 		{
-			controls.Groups[0].Checks[3],
-			"2:45 ../kubernetes/kube-apiserver --secure-port=0 --audit-log-maxage=40 --option",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[3],
+			str:                "2:45 ../kubernetes/kube-apiserver --secure-port=0 --audit-log-maxage=40 --option",
+			strConfig:          "",
+			expectedTestResult: "'--audit-log-maxage' is greater or equal to 30",
 		},
 		{
-			controls.Groups[0].Checks[4],
-			"2:45 ../kubernetes/kube-apiserver --max-backlog=20 --secure-port=0 --audit-log-maxage=40 --option",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[4],
+			str:                "2:45 ../kubernetes/kube-apiserver --max-backlog=20 --secure-port=0 --audit-log-maxage=40 --option",
+			strConfig:          "",
+			expectedTestResult: "'--max-backlog' is lower than 30",
 		},
 		{
-			controls.Groups[0].Checks[5],
-			"2:45 ../kubernetes/kube-apiserver --option --admission-control=WebHook,RBAC ---audit-log-maxage=40",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[5],
+			str:                "2:45 ../kubernetes/kube-apiserver --option --admission-control=WebHook,RBAC ---audit-log-maxage=40",
+			strConfig:          "",
+			expectedTestResult: "'--admission-control' does not have 'AlwaysAdmit'",
 		},
 		{
-			controls.Groups[0].Checks[6],
-			"2:45 .. --kubelet-clientkey=foo --kubelet-client-certificate=bar --admission-control=Webhook,RBAC",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[6],
+			str:                "2:45 .. --kubelet-clientkey=foo --kubelet-client-certificate=bar --admission-control=Webhook,RBAC",
+			strConfig:          "",
+			expectedTestResult: "'--kubelet-client-certificate' is present AND '--kubelet-clientkey' is present",
 		},
 		{
-			controls.Groups[0].Checks[7],
-			"2:45 ..  --secure-port=0 --kubelet-client-certificate=bar --admission-control=Webhook,RBAC",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[7],
+			str:                "2:45 ..  --secure-port=0 --kubelet-client-certificate=bar --admission-control=Webhook,RBAC",
+			strConfig:          "",
+			expectedTestResult: "'--secure-port' is equal to '0' OR '--secure-port' is not present",
 		},
 		{
-			controls.Groups[0].Checks[8],
-			"644",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[8],
+			str:                "permissions=SomeValue",
+			strConfig:          "",
+			expectedTestResult: "'permissions' is equal to 'SomeValue'",
 		},
 		{
-			controls.Groups[0].Checks[9],
-			"640",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[9],
+			str:                "permissions=640",
+			strConfig:          "",
+			expectedTestResult: "permissions has permissions 640, expected 644 or more restrictive",
 		},
 		{
-			controls.Groups[0].Checks[9],
-			"600",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[9],
+			str:                "permissions=600",
+			strConfig:          "",
+			expectedTestResult: "permissions has permissions 600, expected 644 or more restrictive",
 		},
 		{
-			controls.Groups[0].Checks[10],
-			"2:45 ../kubernetes/kube-apiserver --option --admission-control=WebHook,RBAC ---audit-log-maxage=40",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[10],
+			str:                "2:45 ../kubernetes/kube-apiserver --option --admission-control=WebHook,RBAC ---audit-log-maxage=40",
+			strConfig:          "",
+			expectedTestResult: "'--admission-control' has 'RBAC'",
 		},
 		{
-			controls.Groups[0].Checks[11],
-			"2:45 ../kubernetes/kube-apiserver --option --admission-control=WebHook,RBAC ---audit-log-maxage=40",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[11],
+			str:                "2:45 ../kubernetes/kube-apiserver --option --admission-control=WebHook,RBAC ---audit-log-maxage=40",
+			strConfig:          "",
+			expectedTestResult: "'--admission-control' has 'WebHook'",
 		},
 		{
-			controls.Groups[0].Checks[12],
-			"2:45 ../kubernetes/kube-apiserver --option --admission-control=WebHook,Something,RBAC ---audit-log-maxage=40",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[12],
+			str:                "2:45 ../kubernetes/kube-apiserver --option --admission-control=WebHook,Something,RBAC ---audit-log-maxage=40",
+			strConfig:          "",
+			expectedTestResult: "'--admission-control' has 'Something'",
 		},
 		{
-			controls.Groups[0].Checks[13],
-			"2:45 ../kubernetes/kube-apiserver --option --admission-control=Something ---audit-log-maxage=40",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[13],
+			str:                "2:45 ../kubernetes/kube-apiserver --option --admission-control=Something ---audit-log-maxage=40",
+			strConfig:          "",
+			expectedTestResult: "'--admission-control' has 'Something'",
 		},
 		{
 			// check for ':' as argument-value separator, with space between arg and val
-			controls.Groups[0].Checks[14],
-			"2:45 kube-apiserver some-arg: some-val --admission-control=Something ---audit-log-maxage=40",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[14],
+			str:                "2:45 kube-apiserver some-arg: some-val --admission-control=Something ---audit-log-maxage=40",
+			strConfig:          "",
+			expectedTestResult: "'some-arg' is equal to 'some-val'",
 		},
 		{
 			// check for ':' as argument-value separator, with no space between arg and val
-			controls.Groups[0].Checks[14],
-			"2:45 kube-apiserver some-arg:some-val --admission-control=Something ---audit-log-maxage=40",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[14],
+			str:                "2:45 kube-apiserver some-arg:some-val --admission-control=Something ---audit-log-maxage=40",
+			strConfig:          "",
+			expectedTestResult: "'some-arg' is equal to 'some-val'",
 		},
 		{
-			controls.Groups[0].Checks[15],
-			"",
-			"{\"readOnlyPort\": 15000}",
-			"",
+			check:              controls.Groups[0].Checks[15],
+			str:                "",
+			strConfig:          "{\"readOnlyPort\": 15000}",
+			expectedTestResult: "'{.readOnlyPort}' is equal to '15000' OR '{.readOnlyPort}' is greater or equal to 15000 OR '{.readOnlyPort}' is lower or equal to 15000",
 		},
 		{
-			controls.Groups[0].Checks[16],
-			"",
-			"{\"stringValue\": \"WebHook,Something,RBAC\"}",
-			"",
+			check:              controls.Groups[0].Checks[16],
+			str:                "",
+			strConfig:          "{\"stringValue\": \"WebHook,Something,RBAC\"}",
+			expectedTestResult: "'{.stringValue}' is not equal to 'None' AND '{.stringValue}' is not equal to 'webhook,Something,RBAC' AND '{.stringValue}' is equal to 'WebHook,Something,RBAC'",
 		},
 		{
-			controls.Groups[0].Checks[17],
-			"",
-			"{\"trueValue\": true}",
-			"",
+			check:              controls.Groups[0].Checks[17],
+			str:                "",
+			strConfig:          "{\"trueValue\": true}",
+			expectedTestResult: "'{.trueValue}' is not equal to 'somethingElse' AND '{.trueValue}' is not equal to 'false' AND '{.trueValue}' is equal to 'true'",
 		},
 		{
-			controls.Groups[0].Checks[18],
-			"",
-			"{\"readOnlyPort\": 15000}",
-			"",
+			check:              controls.Groups[0].Checks[18],
+			str:                "",
+			strConfig:          "{\"readOnlyPort\": 15000}",
+			expectedTestResult: "'{.notARealField}' is not present",
 		},
 		{
-			controls.Groups[0].Checks[19],
-			"",
-			"{\"authentication\": { \"anonymous\": {\"enabled\": false}}}",
-			"",
+			check:              controls.Groups[0].Checks[19],
+			str:                "",
+			strConfig:          "{\"authentication\": { \"anonymous\": {\"enabled\": false}}}",
+			expectedTestResult: "'{.authentication.anonymous.enabled}' is equal to 'false'",
 		},
 		{
-			controls.Groups[0].Checks[20],
-			"",
-			"readOnlyPort: 15000",
-			"",
+			check:              controls.Groups[0].Checks[20],
+			str:                "",
+			strConfig:          "readOnlyPort: 15000",
+			expectedTestResult: "'{.readOnlyPort}' is greater than 14999",
 		},
 		{
-			controls.Groups[0].Checks[21],
-			"",
-			"readOnlyPort: 15000",
-			"",
+			check:              controls.Groups[0].Checks[21],
+			str:                "",
+			strConfig:          "readOnlyPort: 15000",
+			expectedTestResult: "'{.fieldThatIsUnset}' is not present",
 		},
 		{
-			controls.Groups[0].Checks[22],
-			"",
-			"authentication:\n  anonymous:\n    enabled: false",
-			"",
+			check:              controls.Groups[0].Checks[22],
+			str:                "",
+			strConfig:          "authentication:\n  anonymous:\n    enabled: false",
+			expectedTestResult: "'{.authentication.anonymous.enabled}' is equal to 'false'",
 		},
 		{
-			controls.Groups[0].Checks[26],
-			"",
-			"currentMasterVersion: 1.12.7",
-			"",
+			check:              controls.Groups[0].Checks[26],
+			str:                "",
+			strConfig:          "currentMasterVersion: 1.12.7",
+			expectedTestResult: "'{.currentMasterVersion}' matched by regex expression '^1\\.12.*$'",
 		},
 		{
-			controls.Groups[0].Checks[27],
-			"--peer-client-cert-auth",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[27],
+			str:                "--peer-client-cert-auth",
+			strConfig:          "",
+			expectedTestResult: "'--peer-client-cert-auth' is equal to 'true'",
 		},
 		{
-			controls.Groups[0].Checks[27],
-			"--abc=true --peer-client-cert-auth --efg=false",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[27],
+			str:                "--abc=true --peer-client-cert-auth --efg=false",
+			strConfig:          "",
+			expectedTestResult: "'--peer-client-cert-auth' is equal to 'true'",
 		},
 		{
-			controls.Groups[0].Checks[27],
-			"--abc --peer-client-cert-auth --efg",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[27],
+			str:                "--abc --peer-client-cert-auth --efg",
+			strConfig:          "",
+			expectedTestResult: "'--peer-client-cert-auth' is equal to 'true'",
 		},
 		{
-			controls.Groups[0].Checks[27],
-			"--peer-client-cert-auth=true",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[27],
+			str:                "--peer-client-cert-auth=true",
+			strConfig:          "",
+			expectedTestResult: "'--peer-client-cert-auth' is equal to 'true'",
 		},
 		{
-			controls.Groups[0].Checks[27],
-			"--abc --peer-client-cert-auth=true --efg",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[27],
+			str:                "--abc --peer-client-cert-auth=true --efg",
+			strConfig:          "",
+			expectedTestResult: "'--peer-client-cert-auth' is equal to 'true'",
 		},
 		{
-			controls.Groups[0].Checks[28],
-			"--abc --peer-client-cert-auth=false --efg",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[28],
+			str:                "--abc --peer-client-cert-auth=false --efg",
+			strConfig:          "",
+			expectedTestResult: "'--peer-client-cert-auth' is equal to 'false'",
 		},
 		{
-			controls.Groups[0].Checks[29],
-			"2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
-			"",
-			"SOME_OTHER_ENV=true\nALLOW_PRIVILEGED=false",
+			check:              controls.Groups[0].Checks[29],
+			str:                "2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
+			strConfig:          "",
+			expectedTestResult: "'ALLOW_PRIVILEGED' is present",
+			strEnv:             "SOME_OTHER_ENV=true\nALLOW_PRIVILEGED=false",
 		},
 		{
-			controls.Groups[0].Checks[30],
-			"2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
-			"",
-			"",
+			check:              controls.Groups[0].Checks[30],
+			str:                "2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
+			strConfig:          "",
+			expectedTestResult: "'BASIC_AUTH' is not present",
+			strEnv:             "",
 		},
 		{
-			controls.Groups[0].Checks[31],
-			"2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
-			"",
-			"INSECURE_PORT=0",
+			check:              controls.Groups[0].Checks[31],
+			str:                "2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
+			strConfig:          "",
+			expectedTestResult: "'INSECURE_PORT' is equal to '0'",
+			strEnv:             "INSECURE_PORT=0",
 		},
 		{
-			controls.Groups[0].Checks[32],
-			"2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
-			"",
-			"AUDIT_LOG_MAXAGE=40",
+			check:              controls.Groups[0].Checks[32],
+			str:                "2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
+			strConfig:          "",
+			expectedTestResult: "'AUDIT_LOG_MAXAGE' is greater or equal to 30",
+			strEnv:             "AUDIT_LOG_MAXAGE=40",
 		},
 		{
-			controls.Groups[0].Checks[33],
-			"2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
-			"",
-			"MAX_BACKLOG=20",
+			check:              controls.Groups[0].Checks[33],
+			str:                "2:45 ../kubernetes/kube-apiserver --option1=20,30,40",
+			strConfig:          "",
+			expectedTestResult: "'MAX_BACKLOG' is lower than 30",
+			strEnv:             "MAX_BACKLOG=20",
 		},
 	}
 
 	for _, c := range cases {
-		t.Run(c.Text, func(t *testing.T) {
-			c.Check.AuditOutput = c.str
-			c.Check.AuditConfigOutput = c.strConfig
-			c.Check.AuditEnvOutput = c.strEnv
-			res, err := c.Check.execute()
+		t.Run(c.check.Text, func(t *testing.T) {
+			c.check.AuditOutput = c.str
+			c.check.AuditConfigOutput = c.strConfig
+			c.check.AuditEnvOutput = c.strEnv
+			res, err := c.check.execute()
 			if err != nil {
 				t.Errorf(err.Error())
 			}
 			if !res.testResult {
-				t.Errorf("expected:%v, got:%v", true, res)
+				t.Errorf("Test ID %v - expected:%v, got:%v", c.check.ID, true, res)
+			}
+			if res.ExpectedResult != c.expectedTestResult {
+				t.Errorf("Test ID %v - \nexpected:%v, \ngot:     %v", c.check.ID, c.expectedTestResult, res.ExpectedResult)
 			}
 		})
 	}
@@ -572,256 +581,512 @@ func TestCompareOp(t *testing.T) {
 	cases := []struct {
 		label                 string
 		op                    string
-		flagVal               string
-		compareValue          string
+		flagVal               string // Test output.
+		compareValue          string // Flag value to compare with.
 		expectedResultPattern string
+		flagName              string // Compared flag name.
 		testResult            bool
 	}{
 		// Test Op not matching
-		{label: "empty - op", op: "", flagVal: "", compareValue: "", expectedResultPattern: "", testResult: false},
-		{label: "op=blah", op: "blah", flagVal: "foo", compareValue: "bar", expectedResultPattern: "", testResult: false},
+		{label: "empty - op", op: "", flagVal: "", compareValue: "", expectedResultPattern: "", testResult: false, flagName: ""},
+		{label: "op=blah", op: "blah", flagVal: "foo", compareValue: "bar", expectedResultPattern: "", testResult: false, flagName: ""},
 
 		// Test Op "eq"
-		{label: "op=eq, both empty", op: "eq", flagVal: "", compareValue: "", expectedResultPattern: "'' is equal to ''", testResult: true},
+		{label: "op=eq, both empty", op: "eq", flagVal: "", compareValue: "", expectedResultPattern: "'' is equal to ''", testResult: true, flagName: ""},
 
 		{label: "op=eq, true==true", op: "eq", flagVal: "true",
 			compareValue:          "true",
-			expectedResultPattern: "'true' is equal to 'true'",
-			testResult:            true},
+			expectedResultPattern: "'parameterTrue' is equal to 'true'",
+			testResult:            true,
+			flagName:              "parameterTrue"},
 
 		{label: "op=eq, false==false", op: "eq", flagVal: "false",
 			compareValue:          "false",
-			expectedResultPattern: "'false' is equal to 'false'",
-			testResult:            true},
+			expectedResultPattern: "'parameterFalse' is equal to 'false'",
+			testResult:            true,
+			flagName:              "parameterFalse"},
 
 		{label: "op=eq, false==true", op: "eq", flagVal: "false",
 			compareValue:          "true",
-			expectedResultPattern: "'false' is equal to 'true'",
-			testResult:            false},
+			expectedResultPattern: "'parameterFalse' is equal to 'true'",
+			testResult:            false,
+			flagName:              "parameterFalse"},
 
 		{label: "op=eq, strings match", op: "eq", flagVal: "KubeletConfiguration",
 			compareValue:          "KubeletConfiguration",
-			expectedResultPattern: "'KubeletConfiguration' is equal to 'KubeletConfiguration'",
-			testResult:            true},
+			expectedResultPattern: "'--FlagNameKubeletConf' is equal to 'KubeletConfiguration'",
+			testResult:            true,
+			flagName:              "--FlagNameKubeletConf"},
 
 		{label: "op=eq, flagVal=empty", op: "eq", flagVal: "",
 			compareValue:          "KubeletConfiguration",
-			expectedResultPattern: "'' is equal to 'KubeletConfiguration'",
-			testResult:            false},
+			expectedResultPattern: "'--FlagNameKubeletConf' is equal to 'KubeletConfiguration'",
+			testResult:            false,
+			flagName:              "--FlagNameKubeletConf"},
 
-		{label: "op=eq, compareValue=empty", op: "eq", flagVal: "KubeletConfiguration",
+		{label: "op=eq, compareValue=empty",
+			op:                    "eq",
+			flagVal:               "KubeletConfiguration",
 			compareValue:          "",
-			expectedResultPattern: "'KubeletConfiguration' is equal to ''",
-			testResult:            false},
+			expectedResultPattern: "'--FlagNameKubeletConf' is equal to ''",
+			testResult:            false,
+			flagName:              "--FlagNameKubeletConf"},
 
 		// Test Op "noteq"
-		{label: "op=noteq, both empty", op: "noteq", flagVal: "",
-			compareValue: "", expectedResultPattern: "'' is not equal to ''",
-			testResult: false},
+		{label: "op=noteq, both empty",
+			op:                    "noteq",
+			flagVal:               "",
+			compareValue:          "",
+			expectedResultPattern: "'parameter' is not equal to ''",
+			testResult:            false,
+			flagName:              "parameter"},
 
-		{label: "op=noteq, true!=true", op: "noteq", flagVal: "true",
+		{label: "op=noteq, true!=true",
+			op:                    "noteq",
+			flagVal:               "true",
 			compareValue:          "true",
-			expectedResultPattern: "'true' is not equal to 'true'",
-			testResult:            false},
+			expectedResultPattern: "'parameterTrue' is not equal to 'true'",
+			testResult:            false,
+			flagName:              "parameterTrue"},
 
-		{label: "op=noteq, false!=false", op: "noteq", flagVal: "false",
+		{label: "op=noteq, false!=false",
+			op:                    "noteq",
+			flagVal:               "false",
 			compareValue:          "false",
-			expectedResultPattern: "'false' is not equal to 'false'",
-			testResult:            false},
+			expectedResultPattern: "'parameterFalse' is not equal to 'false'",
+			testResult:            false,
+			flagName:              "parameterFalse"},
 
-		{label: "op=noteq, false!=true", op: "noteq", flagVal: "false",
+		{label: "op=noteq, false!=true",
+			op:                    "noteq",
+			flagVal:               "false",
 			compareValue:          "true",
-			expectedResultPattern: "'false' is not equal to 'true'",
-			testResult:            true},
+			expectedResultPattern: "'parameterFalse' is not equal to 'true'",
+			testResult:            true,
+			flagName:              "parameterFalse"},
 
-		{label: "op=noteq, strings match", op: "noteq", flagVal: "KubeletConfiguration",
+		{label: "op=noteq, strings match",
+			op:                    "noteq",
+			flagVal:               "KubeletConfiguration",
 			compareValue:          "KubeletConfiguration",
-			expectedResultPattern: "'KubeletConfiguration' is not equal to 'KubeletConfiguration'",
-			testResult:            false},
+			expectedResultPattern: "'--FlagNameKubeletConf' is not equal to 'KubeletConfiguration'",
+			testResult:            false,
+			flagName:              "--FlagNameKubeletConf"},
 
-		{label: "op=noteq, flagVal=empty", op: "noteq", flagVal: "",
+		{label: "op=noteq, flagVal=empty",
+			op:                    "noteq",
+			flagVal:               "",
 			compareValue:          "KubeletConfiguration",
-			expectedResultPattern: "'' is not equal to 'KubeletConfiguration'",
-			testResult:            true},
+			expectedResultPattern: "'--FlagNameKubeletConf' is not equal to 'KubeletConfiguration'",
+			testResult:            true,
+			flagName:              "--FlagNameKubeletConf"},
 
-		{label: "op=noteq, compareValue=empty", op: "noteq", flagVal: "KubeletConfiguration",
+		{label: "op=noteq, compareValue=empty",
+			op:                    "noteq",
+			flagVal:               "KubeletConfiguration",
 			compareValue:          "",
-			expectedResultPattern: "'KubeletConfiguration' is not equal to ''",
-			testResult:            true},
+			expectedResultPattern: "'--FlagNameKubeletConf' is not equal to ''",
+			testResult:            true,
+			flagName:              "--FlagNameKubeletConf"},
 
 		// Test Op "gt"
-		{label: "op=gt, both empty", op: "gt", flagVal: "",
-			compareValue: "", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
-		{label: "op=gt, 0 > 0", op: "gt", flagVal: "0",
-			compareValue: "0", expectedResultPattern: "0 is greater than 0",
-			testResult: false},
-		{label: "op=gt, 4 > 5", op: "gt", flagVal: "4",
-			compareValue: "5", expectedResultPattern: "4 is greater than 5",
-			testResult: false},
-		{label: "op=gt, 5 > 4", op: "gt", flagVal: "5",
-			compareValue: "4", expectedResultPattern: "5 is greater than 4",
-			testResult: true},
-		{label: "op=gt, 5 > 5", op: "gt", flagVal: "5",
-			compareValue: "5", expectedResultPattern: "5 is greater than 5",
-			testResult: false},
-		{label: "op=gt, Pikachu > 5", op: "gt", flagVal: "Pikachu",
-			compareValue: "5", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
-		{label: "op=gt, 5 > Bulbasaur", op: "gt", flagVal: "5",
-			compareValue: "Bulbasaur", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
+		{label: "op=gt, both empty",
+			op:                    "gt",
+			flagVal:               "",
+			compareValue:          "",
+			expectedResultPattern: "Invalid Number(s) used for comparison: '' ''",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=gt, 0 > 0",
+			op:           "gt",
+			flagVal:      "0",
+			compareValue: "0", expectedResultPattern: "'flagName' is greater than 0",
+			testResult: false,
+			flagName:   "flagName"},
+		{label: "op=gt, 4 > 5",
+			op:                    "gt",
+			flagVal:               "4",
+			compareValue:          "5",
+			expectedResultPattern: "'flagName' is greater than 5",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=gt, 5 > 4",
+			op:                    "gt",
+			flagVal:               "5",
+			compareValue:          "4",
+			expectedResultPattern: "'flagName' is greater than 4",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=gt, 5 > 5",
+			op:                    "gt",
+			flagVal:               "5",
+			compareValue:          "5",
+			expectedResultPattern: "'flagName' is greater than 5",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=gt, Pikachu > 5",
+			op:                    "gt",
+			flagVal:               "Pikachu",
+			compareValue:          "5",
+			expectedResultPattern: "Invalid Number(s) used for comparison: 'Pikachu' '5'",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=gt, 5 > Bulbasaur",
+			op:                    "gt",
+			flagVal:               "5",
+			compareValue:          "Bulbasaur",
+			expectedResultPattern: "Invalid Number(s) used for comparison: '5' 'Bulbasaur'",
+			testResult:            false,
+			flagName:              "flagName"},
 		// Test Op "lt"
-		{label: "op=lt, both empty", op: "lt", flagVal: "",
-			compareValue: "", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
-		{label: "op=lt, 0 < 0", op: "lt", flagVal: "0",
-			compareValue: "0", expectedResultPattern: "0 is lower than 0",
-			testResult: false},
-		{label: "op=lt, 4 < 5", op: "lt", flagVal: "4",
-			compareValue: "5", expectedResultPattern: "4 is lower than 5",
-			testResult: true},
-		{label: "op=lt, 5 < 4", op: "lt", flagVal: "5",
-			compareValue: "4", expectedResultPattern: "5 is lower than 4",
-			testResult: false},
-		{label: "op=lt, 5 < 5", op: "lt", flagVal: "5",
-			compareValue: "5", expectedResultPattern: "5 is lower than 5",
-			testResult: false},
-		{label: "op=lt, Charmander < 5", op: "lt", flagVal: "Charmander",
-			compareValue: "5", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
-		{label: "op=lt, 5 < Charmeleon", op: "lt", flagVal: "5",
-			compareValue: "Charmeleon", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
+		{label: "op=lt, both empty",
+			op:                    "lt",
+			flagVal:               "",
+			compareValue:          "",
+			expectedResultPattern: "Invalid Number(s) used for comparison: '' ''",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=lt, 0 < 0",
+			op:                    "lt",
+			flagVal:               "0",
+			compareValue:          "0",
+			expectedResultPattern: "'flagName' is lower than 0",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=lt, 4 < 5",
+			op:                    "lt",
+			flagVal:               "4",
+			compareValue:          "5",
+			expectedResultPattern: "'flagName' is lower than 5",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=lt, 5 < 4",
+			op:                    "lt",
+			flagVal:               "5",
+			compareValue:          "4",
+			expectedResultPattern: "'flagName' is lower than 4",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=lt, 5 < 5",
+			op:                    "lt",
+			flagVal:               "5",
+			compareValue:          "5",
+			expectedResultPattern: "'flagName' is lower than 5",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=lt, Charmander < 5",
+			op:                    "lt",
+			flagVal:               "Charmander",
+			compareValue:          "5",
+			expectedResultPattern: "Invalid Number(s) used for comparison: 'Charmander' '5'",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=lt, 5 < Charmeleon",
+			op:                    "lt",
+			flagVal:               "5",
+			compareValue:          "Charmeleon",
+			expectedResultPattern: "Invalid Number(s) used for comparison: '5' 'Charmeleon'",
+			testResult:            false,
+			flagName:              "flagName"},
 		// Test Op "gte"
-		{label: "op=gte, both empty", op: "gte", flagVal: "",
-			compareValue: "", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
-		{label: "op=gte, 0 >= 0", op: "gte", flagVal: "0",
-			compareValue: "0", expectedResultPattern: "0 is greater or equal to 0",
-			testResult: true},
-		{label: "op=gte, 4 >= 5", op: "gte", flagVal: "4",
-			compareValue: "5", expectedResultPattern: "4 is greater or equal to 5",
-			testResult: false},
-		{label: "op=gte, 5 >= 4", op: "gte", flagVal: "5",
-			compareValue: "4", expectedResultPattern: "5 is greater or equal to 4",
-			testResult: true},
-		{label: "op=gte, 5 >= 5", op: "gte", flagVal: "5",
-			compareValue: "5", expectedResultPattern: "5 is greater or equal to 5",
-			testResult: true},
-		{label: "op=gte, Ekans >= 5", op: "gte", flagVal: "Ekans",
-			compareValue: "5", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
-		{label: "op=gte, 4 >= Zubat", op: "gte", flagVal: "4",
-			compareValue: "Zubat", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
+		{label: "op=gte, both empty",
+			op:                    "gte",
+			flagVal:               "",
+			compareValue:          "",
+			expectedResultPattern: "Invalid Number(s) used for comparison: '' ''",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=gte, 0 >= 0",
+			op:                    "gte",
+			flagVal:               "0",
+			compareValue:          "0",
+			expectedResultPattern: "'flagName' is greater or equal to 0",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=gte, 4 >= 5",
+			op:                    "gte",
+			flagVal:               "4",
+			compareValue:          "5",
+			expectedResultPattern: "'flagName' is greater or equal to 5",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=gte, 5 >= 4",
+			op:                    "gte",
+			flagVal:               "5",
+			compareValue:          "4",
+			expectedResultPattern: "'flagName' is greater or equal to 4",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=gte, 5 >= 5",
+			op:                    "gte",
+			flagVal:               "5",
+			compareValue:          "5",
+			expectedResultPattern: "'flagName' is greater or equal to 5",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=gte, Ekans >= 5",
+			op:                    "gte",
+			flagVal:               "Ekans",
+			compareValue:          "5",
+			expectedResultPattern: "Invalid Number(s) used for comparison: 'Ekans' '5'",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=gte, 4 >= Zubat",
+			op:                    "gte",
+			flagVal:               "4",
+			compareValue:          "Zubat",
+			expectedResultPattern: "Invalid Number(s) used for comparison: '4' 'Zubat'",
+			testResult:            false,
+			flagName:              "flagName"},
 		// Test Op "lte"
-		{label: "op=lte, both empty", op: "lte", flagVal: "",
-			compareValue: "", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
-		{label: "op=lte, 0 <= 0", op: "lte", flagVal: "0",
-			compareValue: "0", expectedResultPattern: "0 is lower or equal to 0",
-			testResult: true},
-		{label: "op=lte, 4 <= 5", op: "lte", flagVal: "4",
-			compareValue: "5", expectedResultPattern: "4 is lower or equal to 5",
-			testResult: true},
-		{label: "op=lte, 5 <= 4", op: "lte", flagVal: "5",
-			compareValue: "4", expectedResultPattern: "5 is lower or equal to 4",
-			testResult: false},
-		{label: "op=lte, 5 <= 5", op: "lte", flagVal: "5",
-			compareValue: "5", expectedResultPattern: "5 is lower or equal to 5",
-			testResult: true},
-		{label: "op=lte, Venomoth <= 4", op: "lte", flagVal: "Venomoth",
-			compareValue: "4", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
-		{label: "op=lte, 5 <= Meowth", op: "lte", flagVal: "5",
-			compareValue: "Meowth", expectedResultPattern: "Invalid Number(s) used for comparison",
-			testResult: false},
+		{label: "op=lte, both empty",
+			op:                    "lte",
+			flagVal:               "",
+			compareValue:          "",
+			expectedResultPattern: "Invalid Number(s) used for comparison: '' ''",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=lte, 0 <= 0",
+			op:                    "lte",
+			flagVal:               "0",
+			compareValue:          "0",
+			expectedResultPattern: "'flagName' is lower or equal to 0",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=lte, 4 <= 5",
+			op:                    "lte",
+			flagVal:               "4",
+			compareValue:          "5",
+			expectedResultPattern: "'flagName' is lower or equal to 5",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=lte, 5 <= 4",
+			op:                    "lte",
+			flagVal:               "5",
+			compareValue:          "4",
+			expectedResultPattern: "'flagName' is lower or equal to 4",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=lte, 5 <= 5",
+			op:                    "lte",
+			flagVal:               "5",
+			compareValue:          "5",
+			expectedResultPattern: "'flagName' is lower or equal to 5",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=lte, Venomoth <= 4",
+			op:                    "lte",
+			flagVal:               "Venomoth",
+			compareValue:          "4",
+			expectedResultPattern: "Invalid Number(s) used for comparison: 'Venomoth' '4'",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=lte, 5 <= Meowth",
+			op:                    "lte",
+			flagVal:               "5",
+			compareValue:          "Meowth",
+			expectedResultPattern: "Invalid Number(s) used for comparison: '5' 'Meowth'",
+			testResult:            false,
+			flagName:              "flagName"},
 
 		// Test Op "has"
-		{label: "op=has, both empty", op: "has", flagVal: "",
-			compareValue: "", expectedResultPattern: "'' has ''",
-			testResult: true},
-		{label: "op=has, flagVal=empty", op: "has", flagVal: "",
-			compareValue: "blah", expectedResultPattern: "'' has 'blah'",
-			testResult: false},
-		{label: "op=has, compareValue=empty", op: "has", flagVal: "blah",
-			compareValue: "", expectedResultPattern: "'blah' has ''",
-			testResult: true},
-		{label: "op=has, 'blah' has 'la'", op: "has", flagVal: "blah",
-			compareValue: "la", expectedResultPattern: "'blah' has 'la'",
-			testResult: true},
-		{label: "op=has, 'blah' has 'LA'", op: "has", flagVal: "blah",
-			compareValue: "LA", expectedResultPattern: "'blah' has 'LA'",
-			testResult: false},
-		{label: "op=has, 'blah' has 'lo'", op: "has", flagVal: "blah",
-			compareValue: "lo", expectedResultPattern: "'blah' has 'lo'",
-			testResult: false},
+		{label: "op=has, both empty",
+			op:                    "has",
+			flagVal:               "",
+			compareValue:          "",
+			expectedResultPattern: "'flagName' has ''",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=has, flagVal=empty",
+			op:                    "has",
+			flagVal:               "",
+			compareValue:          "blah",
+			expectedResultPattern: "'flagName' has 'blah'",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=has, compareValue=empty",
+			op:                    "has",
+			flagVal:               "blah",
+			compareValue:          "",
+			expectedResultPattern: "'flagName-blah' has ''",
+			testResult:            true,
+			flagName:              "flagName-blah"},
+		{label: "op=has, 'blah' has 'la'",
+			op:                    "has",
+			flagVal:               "blah",
+			compareValue:          "la",
+			expectedResultPattern: "'flagName-blah' has 'la'",
+			testResult:            true,
+			flagName:              "flagName-blah"},
+		{label: "op=has, 'blah' has 'LA'",
+			op:                    "has",
+			flagVal:               "blah",
+			compareValue:          "LA",
+			expectedResultPattern: "'flagName-blah' has 'LA'",
+			testResult:            false,
+			flagName:              "flagName-blah"},
+		{label: "op=has, 'blah' has 'lo'",
+			op:                    "has",
+			flagVal:               "blah",
+			compareValue:          "lo",
+			expectedResultPattern: "'flagName-blah' has 'lo'",
+			testResult:            false,
+			flagName:              "flagName-blah"},
 
 		// Test Op "nothave"
-		{label: "op=nothave, both empty", op: "nothave", flagVal: "",
-			compareValue: "", expectedResultPattern: " '' not have ''",
-			testResult: false},
-		{label: "op=nothave, flagVal=empty", op: "nothave", flagVal: "",
-			compareValue: "blah", expectedResultPattern: " '' not have 'blah'",
-			testResult: true},
-		{label: "op=nothave, compareValue=empty", op: "nothave", flagVal: "blah",
-			compareValue: "", expectedResultPattern: " 'blah' not have ''",
-			testResult: false},
-		{label: "op=nothave, 'blah' not have 'la'", op: "nothave", flagVal: "blah",
-			compareValue: "la", expectedResultPattern: " 'blah' not have 'la'",
-			testResult: false},
-		{label: "op=nothave, 'blah' not have 'LA'", op: "nothave", flagVal: "blah",
-			compareValue: "LA", expectedResultPattern: " 'blah' not have 'LA'",
-			testResult: true},
-		{label: "op=nothave, 'blah' not have 'lo'", op: "nothave", flagVal: "blah",
-			compareValue: "lo", expectedResultPattern: " 'blah' not have 'lo'",
-			testResult: true},
+		{label: "op=nothave, both empty",
+			op:                    "nothave",
+			flagVal:               "",
+			compareValue:          "",
+			expectedResultPattern: "'flagName' does not have ''",
+			testResult:            false,
+			flagName:              "flagName"},
+		{label: "op=nothave, flagVal=empty",
+			op:                    "nothave",
+			flagVal:               "",
+			compareValue:          "blah",
+			expectedResultPattern: "'flagName' does not have 'blah'",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=nothave, compareValue=empty",
+			op:                    "nothave",
+			flagVal:               "blah",
+			compareValue:          "",
+			expectedResultPattern: "'flagName-blah' does not have ''",
+			testResult:            false,
+			flagName:              "flagName-blah"},
+		{label: "op=nothave, 'blah' not have 'la'",
+			op:                    "nothave",
+			flagVal:               "blah",
+			compareValue:          "la",
+			expectedResultPattern: "'flagName-blah' does not have 'la'",
+			testResult:            false,
+			flagName:              "flagName-blah"},
+		{label: "op=nothave, 'blah' not have 'LA'",
+			op:                    "nothave",
+			flagVal:               "blah",
+			compareValue:          "LA",
+			expectedResultPattern: "'flagName-blah' does not have 'LA'",
+			testResult:            true,
+			flagName:              "flagName-blah"},
+		{label: "op=nothave, 'blah' not have 'lo'",
+			op:                    "nothave",
+			flagVal:               "blah",
+			compareValue:          "lo",
+			expectedResultPattern: "'flagName-blah' does not have 'lo'",
+			testResult:            true,
+			flagName:              "flagName-blah"},
 
 		// Test Op "regex"
-		{label: "op=regex, both empty", op: "regex", flagVal: "",
-			compareValue: "", expectedResultPattern: " '' matched by ''",
-			testResult: true},
-		{label: "op=regex, flagVal=empty", op: "regex", flagVal: "",
-			compareValue: "blah", expectedResultPattern: " '' matched by 'blah'",
-			testResult: false},
+		{label: "op=regex, both empty",
+			op:                    "regex",
+			flagVal:               "",
+			compareValue:          "",
+			expectedResultPattern: "'flagName' matched by regex expression ''",
+			testResult:            true,
+			flagName:              "flagName"},
+		{label: "op=regex, flagVal=empty",
+			op:                    "regex",
+			flagVal:               "",
+			compareValue:          "blah",
+			expectedResultPattern: "'flagName' matched by regex expression 'blah'",
+			testResult:            false,
+			flagName:              "flagName"},
 
 		// Test Op "valid_elements"
-		{label: "op=valid_elements, valid_elements both empty", op: "valid_elements", flagVal: "",
-			compareValue: "", expectedResultPattern: "'' contains valid elements from ''",
-			testResult: true},
+		{label: "op=valid_elements, valid_elements both empty",
+			op:                    "valid_elements",
+			flagVal:               "",
+			compareValue:          "",
+			expectedResultPattern: "'flagWithMultipleElements' contains valid elements from ''",
+			testResult:            true,
+			flagName:              "flagWithMultipleElements"},
 
-		{label: "op=valid_elements, valid_elements flagVal empty", op: "valid_elements", flagVal: "",
-			compareValue: "a,b", expectedResultPattern: "'' contains valid elements from 'a,b'",
-			testResult: false},
+		{label: "op=valid_elements, valid_elements flagVal empty",
+			op:                    "valid_elements",
+			flagVal:               "",
+			compareValue:          "a,b",
+			expectedResultPattern: "'flagWithMultipleElements' contains valid elements from 'a,b'",
+			testResult:            false,
+			flagName:              "flagWithMultipleElements"},
+
+		{label: "op=valid_elements, valid_elements compareValue empty",
+			op:                    "valid_elements",
+			flagVal:               "a,b",
+			compareValue:          "",
+			expectedResultPattern: "'flagWithMultipleElements' contains valid elements from ''",
+			testResult:            false,
+			flagName:              "flagWithMultipleElements"},
+		{label: "op=valid_elements, valid_elements two list equals",
+			op:                    "valid_elements",
+			flagVal:               "a,b,c",
+			compareValue:          "a,b,c",
+			expectedResultPattern: "'flagWithMultipleElements' contains valid elements from 'a,b,c'",
+			testResult:            true,
+			flagName:              "flagWithMultipleElements"},
+		{label: "op=valid_elements, valid_elements partial flagVal valid",
+			op:                    "valid_elements",
+			flagVal:               "a,c",
+			compareValue:          "a,b,c",
+			expectedResultPattern: "'flagWithMultipleElements' contains valid elements from 'a,b,c'",
+			testResult:            true,
+			flagName:              "flagWithMultipleElements"},
+		{label: "op=valid_elements, valid_elements partial compareValue valid",
+			op:                    "valid_elements",
+			flagVal:               "a,b,c",
+			compareValue:          "a,c",
+			expectedResultPattern: "'flagWithMultipleElements' contains valid elements from 'a,c'",
+			testResult:            false,
+			flagName:              "flagWithMultipleElements"},
 
-		{label: "op=valid_elements, valid_elements expectedResultPattern empty", op: "valid_elements", flagVal: "a,b",
-			compareValue: "", expectedResultPattern: "'a,b' contains valid elements from ''",
-			testResult: false},
 		// Test Op "bitmask"
-		{label: "op=bitmask, 644 AND 640", op: "bitmask", flagVal: "640",
-			compareValue: "644", expectedResultPattern: "bitmask '640' AND '644'",
-			testResult: true},
-		{label: "op=bitmask, 644 AND 777", op: "bitmask", flagVal: "777",
-			compareValue: "644", expectedResultPattern: "bitmask '777' AND '644'",
-			testResult: false},
-		{label: "op=bitmask, 644 AND 444", op: "bitmask", flagVal: "444",
-			compareValue: "644", expectedResultPattern: "bitmask '444' AND '644'",
-			testResult: true},
-		{label: "op=bitmask, 644 AND 211", op: "bitmask", flagVal: "211",
-			compareValue: "644", expectedResultPattern: "bitmask '211' AND '644'",
-			testResult: false},
-		{label: "op=bitmask, Harry AND 211", op: "bitmask", flagVal: "Harry",
-			compareValue: "644", expectedResultPattern: "Not numeric value - flag: Harry",
-			testResult: false},
-		{label: "op=bitmask, 644 AND Potter", op: "bitmask", flagVal: "211",
-			compareValue: "Potter", expectedResultPattern: "Not numeric value - flag: Potter",
-			testResult: false},
+		{label: "op=bitmask, 644 AND 640",
+			op:                    "bitmask",
+			flagVal:               "640",
+			compareValue:          "644",
+			expectedResultPattern: "etc/fileExamplePermission640 has permissions 640, expected 644 or more restrictive",
+			testResult:            true,
+			flagName:              "etc/fileExamplePermission640"},
+		{label: "op=bitmask, 644 AND 777",
+			op:                    "bitmask",
+			flagVal:               "777",
+			compareValue:          "644",
+			expectedResultPattern: "etc/fileExamplePermission777 has permissions 777, expected 644 or more restrictive",
+			testResult:            false,
+			flagName:              "etc/fileExamplePermission777"},
+		{label: "op=bitmask, 644 AND 444",
+			op:                    "bitmask",
+			flagVal:               "444",
+			compareValue:          "644",
+			expectedResultPattern: "etc/fileExamplePermission444 has permissions 444, expected 644 or more restrictive",
+			testResult:            true,
+			flagName:              "etc/fileExamplePermission444"},
+		{label: "op=bitmask, 644 AND 211",
+			op:                    "bitmask",
+			flagVal:               "211",
+			compareValue:          "644",
+			expectedResultPattern: "etc/fileExamplePermission211 has permissions 211, expected 644 or more restrictive",
+			testResult:            false,
+			flagName:              "etc/fileExamplePermission211"},
+		{label: "op=bitmask, Harry AND 211",
+			op:                    "bitmask",
+			flagVal:               "Harry",
+			compareValue:          "644",
+			expectedResultPattern: "Not numeric value - flag: Harry",
+			testResult:            false,
+			flagName:              "etc/fileExample"},
+		{label: "op=bitmask, 644 AND Potter",
+			op:                    "bitmask",
+			flagVal:               "211",
+			compareValue:          "Potter",
+			expectedResultPattern: "Not numeric value - flag: Potter",
+			testResult:            false,
+			flagName:              "etc/fileExample"},
 	}
 
 	for _, c := range cases {
 		t.Run(c.label, func(t *testing.T) {
-			expectedResultPattern, testResult := compareOp(c.op, c.flagVal, c.compareValue)
+			expectedResultPattern, testResult := compareOp(c.op, c.flagVal, c.compareValue, c.flagName)
 			if expectedResultPattern != c.expectedResultPattern {
 				t.Errorf("'expectedResultPattern' did not match - op: %q expected:%q  got:%q", c.op, c.expectedResultPattern, expectedResultPattern)
 			}