diff --git a/README.md b/README.md index c9ae166..06a9fae 100644 --- a/README.md +++ b/README.md @@ -195,17 +195,7 @@ You can also define jsonpath and yamlpath tests using the following syntax: ``` tests: -- jsonpath: - set: - compare: - op: - value: -... -``` - -``` -tests: -- yamlpath: +- path: set: compare: op: diff --git a/cfg/1.11-json/config.yaml b/cfg/1.11-json/config.yaml index 9e923de..b34336d 100644 --- a/cfg/1.11-json/config.yaml +++ b/cfg/1.11-json/config.yaml @@ -8,9 +8,6 @@ # federatedControls: ./cfg/federated.yaml # Master nodes are controlled by EKS and not user-accessible -master: - components: [] - node: kubernetes: confs: diff --git a/cfg/1.11-json/node.yaml b/cfg/1.11-json/node.yaml index 3bd277b..88ae739 100644 --- a/cfg/1.11-json/node.yaml +++ b/cfg/1.11-json/node.yaml @@ -32,7 +32,7 @@ groups: audit: "cat $kubeletconf" tests: test_items: - - jsonpath: "{.authentication.anonymous.enabled}" + - path: "{.authentication.anonymous.enabled}" compare: op: eq value: false @@ -54,7 +54,7 @@ groups: audit: "cat $kubeletconf" tests: test_items: - - jsonpath: "{.authorization.mode}" + - path: "{.authorization.mode}" compare: op: noteq value: "AlwaysAllow" @@ -75,7 +75,7 @@ groups: audit: "cat $kubeletconf" tests: test_items: - - jsonpath: "{.authentication.x509.clientCAFile}" + - path: "{.authentication.x509.clientCAFile}" set: true remediation: | If using a Kubelet config file, edit the file to set authentication: x509: clientCAFile to @@ -95,9 +95,9 @@ groups: tests: bin_op: or test_items: - - jsonpath: "{.readOnlyPort}" + - path: "{.readOnlyPort}" set: false - - jsonpath: "{.readOnlyPort}" + - path: "{.readOnlyPort}" compare: op: eq value: "0" @@ -119,9 +119,9 @@ groups: tests: bin_op: or test_items: - - jsonpath: "{.streamingConnectionIdleTimeout}" + - path: "{.streamingConnectionIdleTimeout}" set: false - - jsonpath: "{.streamingConnectionIdleTimeout}" + - path: "{.streamingConnectionIdleTimeout}" compare: op: noteq value: 0 @@ -143,7 +143,7 @@ groups: audit: "cat $kubeletconf" tests: test_items: - - jsonpath: "{.protectKernelDefaults}" + - path: "{.protectKernelDefaults}" compare: op: eq value: true @@ -165,9 +165,9 @@ groups: tests: bin_op: or test_items: - - jsonpath: "{.makeIPTablesUtilChains}" + - path: "{.makeIPTablesUtilChains}" set: false - - jsonpath: "{.makeIPTablesUtilChains}" + - path: "{.makeIPTablesUtilChains}" compare: op: eq value: true @@ -188,7 +188,7 @@ groups: audit: "cat $kubeletconf" tests: test_items: - - jsonpath: "{.hostnameOverride}" + - path: "{.hostnameOverride}" set: false remediation: | Edit the kubelet service file $kubeletsvc @@ -204,7 +204,7 @@ groups: audit: "cat $kubeletconf" tests: test_items: - - jsonpath: "{.eventRecordQPS}" + - path: "{.eventRecordQPS}" compare: op: eq value: 0 @@ -226,9 +226,9 @@ groups: tests: bin_op: and test_items: - - jsonpath: "{.tlsCertFile}" + - path: "{.tlsCertFile}" set: true - - jsonpath: "{.tlsPrivateKeyFile}" + - path: "{.tlsPrivateKeyFile}" set: true remediation: | If using a Kubelet config file, edit the file to set tlsCertFile to the location of the certificate @@ -250,12 +250,12 @@ groups: tests: bin_op: or test_items: - - jsonpath: "{.cadvisorPort}" + - path: "{.cadvisorPort}" compare: op: eq value: 0 set: true - - jsonpath: "{.cadvisorPort}" + - path: "{.cadvisorPort}" set: false remediation: | Edit the kubelet service file $kubeletsvc @@ -272,9 +272,9 @@ groups: tests: bin_op: or test_items: - - jsonpath: "{.rotateCertificates}" + - path: "{.rotateCertificates}" set: false - - jsonpath: "{.rotateCertificates}" + - path: "{.rotateCertificates}" compare: op: noteq value: "false" @@ -293,7 +293,7 @@ groups: audit: "cat $kubeletconf" tests: test_items: - - jsonpath: "{.featureGates.RotateKubeletServerCertificate}" + - path: "{.featureGates.RotateKubeletServerCertificate}" compare: op: eq value: true @@ -312,7 +312,7 @@ groups: audit: "cat $kubeletconf" tests: test_items: - - jsonpath: "{.tlsCipherSuites}" + - path: "{.tlsCipherSuites}" compare: op: eq value: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256" diff --git a/check/data b/check/data index c474e6a..116a5f9 100644 --- a/check/data +++ b/check/data @@ -171,17 +171,17 @@ groups: text: "jsonpath correct value on field" tests: test_items: - - jsonpath: "{.readOnlyPort}" + - path: "{.readOnlyPort}" compare: op: eq value: 15000 set: true - - jsonpath: "{.readOnlyPort}" + - path: "{.readOnlyPort}" compare: op: gte value: 15000 set: true - - jsonpath: "{.readOnlyPort}" + - path: "{.readOnlyPort}" compare: op: lte value: 15000 @@ -191,17 +191,17 @@ groups: text: "jsonpath correct case-sensitive value on string field" tests: test_items: - - jsonpath: "{.stringValue}" + - path: "{.stringValue}" compare: op: noteq value: "None" set: true - - jsonpath: "{.stringValue}" + - path: "{.stringValue}" compare: op: noteq value: "webhook,Something,RBAC" set: true - - jsonpath: "{.stringValue}" + - path: "{.stringValue}" compare: op: eq value: "WebHook,Something,RBAC" @@ -211,17 +211,17 @@ groups: text: "jsonpath correct value on boolean field" tests: test_items: - - jsonpath: "{.trueValue}" + - path: "{.trueValue}" compare: op: noteq value: somethingElse set: true - - jsonpath: "{.trueValue}" + - path: "{.trueValue}" compare: op: noteq value: false set: true - - jsonpath: "{.trueValue}" + - path: "{.trueValue}" compare: op: eq value: true @@ -231,14 +231,14 @@ groups: text: "jsonpath field absent" tests: test_items: - - jsonpath: "{.notARealField}" + - path: "{.notARealField}" set: false - id: 19 text: "jsonpath correct value on nested field" tests: test_items: - - jsonpath: "{.authentication.anonymous.enabled}" + - path: "{.authentication.anonymous.enabled}" compare: op: eq value: "false" @@ -248,7 +248,7 @@ groups: text: "yamlpath correct value on field" tests: test_items: - - yamlpath: "{.readOnlyPort}" + - path: "{.readOnlyPort}" compare: op: gt value: 14999 @@ -258,41 +258,41 @@ groups: text: "yamlpath field absent" tests: test_items: - - yamlpath: "{.fieldThatIsUnset}" + - path: "{.fieldThatIsUnset}" set: false - id: 22 text: "yamlpath correct value on nested field" tests: test_items: - - yamlpath: "{.authentication.anonymous.enabled}" + - path: "{.authentication.anonymous.enabled}" compare: op: eq value: "false" set: true - id: 23 - text: "jsonpath on invalid json" + text: "path on invalid json" tests: test_items: - - jsonpath: "{.authentication.anonymous.enabled}" + - path: "{.authentication.anonymous.enabled}" compare: op: eq value: "false" set: true - id: 24 - text: "jsonpath with broken expression" + text: "path with broken expression" tests: test_items: - - jsonpath: "{.missingClosingBrace" + - path: "{.missingClosingBrace" set: true - id: 25 text: "yamlpath on invalid yaml" tests: test_items: - - yamlpath: "{.authentication.anonymous.enabled}" + - path: "{.authentication.anonymous.enabled}" compare: op: eq value: "false" diff --git a/check/test.go b/check/test.go index 924e1c4..9ddb469 100644 --- a/check/test.go +++ b/check/test.go @@ -42,13 +42,12 @@ const ( ) type testItem struct { - Flag string - Jsonpath string - Yamlpath string - Output string - Value string - Set bool - Compare compare + Flag string + Path string + Output string + Value string + Set bool + Compare compare } type compare struct { @@ -74,40 +73,34 @@ func (t *testItem) execute(s string) *testOutput { // Flag comparison: check if the flag is present in the input match = strings.Contains(s, t.Flag) } else { - // Means either t.Jsonpath != "" or t.Yamlpath != "" - // Find out and convert the input as needed + // Path != "" - we don't know whether it's YAML or JSON but + // we can just try one then the other buf := new(bytes.Buffer) var jsonInterface interface{} - var pathExpression string - if t.Yamlpath != "" { - pathExpression = t.Yamlpath - err := yaml.Unmarshal([]byte(s), &jsonInterface) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to load YAML from provided input \"%s\": %v\n", s, err) - return failTestItem("failed to load YAML") - } - } else if t.Jsonpath != "" { - pathExpression = t.Jsonpath + if t.Path != "" { err := json.Unmarshal([]byte(s), &jsonInterface) if err != nil { - fmt.Fprintf(os.Stderr, "failed to load JSON from provided input: \"%s\": %v\n", s, err) - return failTestItem("failed to load JSON") + err := yaml.Unmarshal([]byte(s), &jsonInterface) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to load YAML or JSON from provided input \"%s\": %v\n", s, err) + return failTestItem("failed to load YAML or JSON") + } } } // Parse the jsonpath/yamlpath expression... j := jsonpath.New("jsonpath") j.AllowMissingKeys(true) - err := j.Parse(pathExpression) + err := j.Parse(t.Path) if err != nil { - fmt.Fprintf(os.Stderr, "unable to parse path expression \"%s\": %v\n", pathExpression, err) + fmt.Fprintf(os.Stderr, "unable to parse path expression \"%s\": %v\n", t.Path, err) return failTestItem("unable to parse path expression") } err = j.Execute(buf, jsonInterface) if err != nil { - fmt.Fprintf(os.Stderr, "error executing path expression \"%s\": %v\n", pathExpression, err) + fmt.Fprintf(os.Stderr, "error executing path expression \"%s\": %v\n", t.Path, err) return failTestItem("error executing path expression") } @@ -123,7 +116,7 @@ func (t *testItem) execute(s string) *testOutput { if t.Flag != "" { // Expects flags in the form; // --flag=somevalue - // flag: somevalue + // flag: somevalue // --flag // somevalue pttn := `(` + t.Flag + `)(=|: *)*([^\s]*) *`