diff --git a/applications/openshift/api-server/api_server_request_timeout/rule.yml b/applications/openshift/api-server/api_server_request_timeout/rule.yml index 67e87df03ac..8a7562e14dd 100644 --- a/applications/openshift/api-server/api_server_request_timeout/rule.yml +++ b/applications/openshift/api-server/api_server_request_timeout/rule.yml @@ -40,3 +40,17 @@ ocil: |- Run the following command:
$ oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments["min-request-timeout"]'
The output should return
300
. + +template: + name: yamlfile_value + vars: + ocp_data: "true" + entity_check: "at least one" + filepath: /api/v1/namespaces/openshift-kube-apiserver/configmaps/config + yamlpath: '.data["config.yaml"]' + xccdf_variable: var_api_min_request_timeout + embedded_data: "true" + values: + - value: '"apiServerArguments":{.*"min-request-timeout":\["(\d*)"\]' + operation: "pattern match" + type: "string" diff --git a/applications/openshift/api-server/api_server_request_timeout/tests/ocp4/e2e.yml b/applications/openshift/api-server/api_server_request_timeout/tests/ocp4/e2e.yml new file mode 100644 index 00000000000..ed3f08d15e2 --- /dev/null +++ b/applications/openshift/api-server/api_server_request_timeout/tests/ocp4/e2e.yml @@ -0,0 +1,2 @@ +--- +default_result: PASS \ No newline at end of file diff --git a/applications/openshift/api-server/var_api_min_request_timeout.var b/applications/openshift/api-server/var_api_min_request_timeout.var new file mode 100644 index 00000000000..ac2b992bed6 --- /dev/null +++ b/applications/openshift/api-server/var_api_min_request_timeout.var @@ -0,0 +1,15 @@ +documentation_complete: true + +title: 'API Server Request Timeout' + +description: 'Enter API Server Request Timeout' + +type: string + +operator: equals + +interactive: false + +options: + 300: "300" + default: "3600" diff --git a/applications/openshift/kubelet/kubelet_eviction_thresholds_set_soft_memory_available/rule.yml b/applications/openshift/kubelet/kubelet_eviction_thresholds_set_soft_memory_available/rule.yml new file mode 100644 index 00000000000..faca91a8061 --- /dev/null +++ b/applications/openshift/kubelet/kubelet_eviction_thresholds_set_soft_memory_available/rule.yml @@ -0,0 +1,72 @@ +documentation_complete: true + +prodtype: ocp4 + +title: 'Ensure Eviction threshold Settings Are Set - evictionSoft: memory.available' + +description: |- +

Two types of garbage collection are performed on an OpenShift Container Platform node:

+ + + +

+ Container garbage collection can be performed using eviction thresholds. + Image garbage collection relies on disk usage as reported by cAdvisor on the + node to decide which images to remove from the node. +

+ +

+ The OpenShift administrator can configure how OpenShift Container Platform + performs garbage collection by creating a kubeletConfig object for each + Machine Config Pool using any combination of the following: +

+ + + +

+ To configure, follow the directions in + {{{ weblink(link="https://docs.openshift.com/container-platform/4.5/nodes/nodes/nodes-nodes-garbage-collection.html#nodes-nodes-garbage-collection-configuring_nodes-nodes-configuring", + text="the documentation") }}} +

+ +

+ This rule pertains to the memory.available setting of the evictionSoft + section. +

+ +rationale: |- + Garbage collection is important to ensure sufficient resource availability + and avoiding degraded performance and availability. In the worst case, the + system might crash or just be unusable for a long period of time. + Based on your system resources and tests, choose an appropriate threshold + value to activate garbage collection. + +severity: medium + +references: + cis: 1.3.1 + +identifiers: + cce@ocp4: CCE-84222-9 + +ocil_clause: 'memory.available is not set in evictionSoft section' + +ocil: |- + Run the following command on the kubelet node(s): +
$ oc debug -q node/$NODE -- jq -r '.evictionSoft."memory.available"' /host/etc/kubernetes/kubelet.conf
+ and make sure it outputs +
{{{ xccdf_value("var_kubelet_evictionsoft_memory_available") }}}
+ +template: + name: yamlfile_value + vars: + filepath: /etc/kubernetes/kubelet.conf + yamlpath: ".evictionSoft['memory.available']" + xccdf_variable: var_kubelet_evictionsoft_memory_available diff --git a/applications/openshift/kubelet/var_kubelet_evictionsoft_memory_available.var b/applications/openshift/kubelet/var_kubelet_evictionsoft_memory_available.var new file mode 100644 index 00000000000..607631aea2e --- /dev/null +++ b/applications/openshift/kubelet/var_kubelet_evictionsoft_memory_available.var @@ -0,0 +1,14 @@ +documentation_complete: true + +title: 'Configure Kubelet EvictionSoft Memory Avilable' + +description: 'Memory Available for the EvictionSoft threshold to trigger.' + +type: string + +operator: equals + +interactive: false + +options: + default: 500Mi diff --git a/docs/manual/developer/06_contributing_with_content.md b/docs/manual/developer/06_contributing_with_content.md index 00497ec4d0a..eb59939ccbb 100644 --- a/docs/manual/developer/06_contributing_with_content.md +++ b/docs/manual/developer/06_contributing_with_content.md @@ -1744,12 +1744,21 @@ The selected value can be changed in the profile (consult the actual variable fo Possible options are `all_exist`, `any_exist`, `at_least_one_exists`, `none_exist`, `only_one_exists`. + - **xccdf_variable** - XCCDF variable selector. Use this field if the comparison involves + checking for a value selected by a XCCDF variable. + + - **embedded_data** - if set to `"true"` and used combined with `xccdf_variable`, the data retrieved by `yamlpath` + is considered as a blob and the field `value` has to contain a capture regex. + - **values** - a list of dictionaries with values to check, where: - **key** - the yaml key to check, optional. Used when the yamlpath expression yields a map. - - **value** - the value to check. + - **value** - the value to check. If used in combination with + `xccdf_variable` and `embedded_data`, this field must have a + regex with a capture group. The value captured by the regex + will be compared with value of variable referenced by `xccdf_variable`. - **type** ([SimpleDatatypeEnumeration](https://github.com/OVALProject/Language/blob/master/docs/oval-common-schema.md#---simpledatatypeenumeration---)) - diff --git a/ocp4/profiles/cis-node.profile b/ocp4/profiles/cis-node.profile index c6501fa7416..e17595e19e8 100644 --- a/ocp4/profiles/cis-node.profile +++ b/ocp4/profiles/cis-node.profile @@ -112,6 +112,8 @@ selections: - file_permissions_etcd_pki_cert_files # 1.1.21 Ensure that the OpenShift PKI key file permissions are set to 600 - file_permissions_openshift_pki_key_files + #### 1.3 Controller Manager + # 1.3.1 Ensure that garbage collection is configured as appropriate (Manual) ### 2 etcd # 2.7 Ensure that a unique Certificate Authority is used for etcd @@ -121,6 +123,7 @@ selections: ### #### 3.2 Logging # 3.2.1 Ensure that a minimal audit policy is created + - kubelet_eviction_thresholds_set_soft_memory_available ### 4 Worker Nodes ### diff --git a/ocp4/profiles/cis.profile b/ocp4/profiles/cis.profile index e2a9ccef6cc..0cff9c162e5 100644 --- a/ocp4/profiles/cis.profile +++ b/ocp4/profiles/cis.profile @@ -93,7 +93,7 @@ selections: # (jhrozek) Temporarily disabling the rule because the benchmark # specifies one value (60) for the request-timeout parameter, while we # use 3600 in OCP. It is unclear if this value is appropriate... - # - api_server_request_timeout + - api_server_request_timeout # 1.2.27 Ensure that the --service-account-lookup argument is set to true - api_server_service_account_lookup # 1.2.28 Ensure that the --service-account-key-file argument is set as appropriate @@ -115,7 +115,6 @@ selections: # 1.2.35 Ensure that the API Server only makes use of Strong Cryptographic Ciphers - api_server_tls_cipher_suites #### 1.3 Controller Manager - # 1.3.1 Ensure that garbage collection is configured as appropriate (Manual) # 1.3.2 Ensure that controller manager healthz endpoints are protected by RBAC. (Automated) - rbac_debug_role_protects_pprof # 1.3.3 Ensure that the --use-service-account-credentials argument is set to true diff --git a/shared/references/cce-redhat-avail.txt b/shared/references/cce-redhat-avail.txt index ed14c14be77..1df5db35b51 100644 --- a/shared/references/cce-redhat-avail.txt +++ b/shared/references/cce-redhat-avail.txt @@ -577,7 +577,6 @@ CCE-84215-3 CCE-84217-9 CCE-84218-7 CCE-84221-1 -CCE-84222-9 CCE-84223-7 CCE-84224-5 CCE-84225-2 diff --git a/shared/templates/yamlfile_value/oval.template b/shared/templates/yamlfile_value/oval.template index 3821bbf62ec..21d63762ba2 100644 --- a/shared/templates/yamlfile_value/oval.template +++ b/shared/templates/yamlfile_value/oval.template @@ -25,12 +25,39 @@ {{{ FILEPATH }}} {{% endif %}} - +{{% if not XCCDF_VARIABLE or (XCCDF_VARIABLE and not EMBEDDED_DATA) %}} +{{% else %}} + + + + + + + local_variable_{{{ rule_id }}} + + + + + + + {{% for val in VALUES %}} + + + + + + {{% endfor %}} + +{{% endif %}} + +{{% if XCCDF_VARIABLE %}} + +{{% endif %}} {{% if OCP_DATA %}} {{{ YAMLPATH }}} + {{% if not XCCDF_VARIABLE or (XCCDF_VARIABLE and not EMBEDDED_DATA) %}} + {{% if XCCDF_VARIABLE and not EMBEDDED_DATA %}} + {{% set name = "#" if not VALUES else (VALUES|first).key|default("#")|escape_yaml_key %}} + {{% set datatype = "string" if not VALUES else (VALUES|first).type|default("string") %}} + + {{% else %}} {{% for val in VALUES %}} {{{ val.value }}} {{% endfor %}} + {{% endif %}} + {{% endif %}} {{% if OCP_DATA %}} @@ -62,3 +97,4 @@ {{% endif %}} + diff --git a/shared/templates/yamlfile_value/template.py b/shared/templates/yamlfile_value/template.py index 1c9347a195a..60168da305b 100644 --- a/shared/templates/yamlfile_value/template.py +++ b/shared/templates/yamlfile_value/template.py @@ -1,3 +1,12 @@ def preprocess(data, lang): + + if data.get("xccdf_variable") and data.get("embedded_data") == "true": + if not data.get("values"): + raise ValueError( + "You should specify a capture regex in the 'value' field " + "when querying for a 'xccdf_value' that returns an embedded value. " + "Rule ID: {}".format(data["_rule_id"])) + + data["embedded_data"] = data.get("embedded_data", "false") == "true" data["ocp_data"] = data.get("ocp_data", "false") == "true" return data