Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add variable support to yamlfile_value template #6563

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,17 @@ ocil: |-
Run the following command:
<pre>$ oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments["min-request-timeout"]'</pre>
The output should return <pre>300</pre>.

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"
ggbecker marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
default_result: PASS
15 changes: 15 additions & 0 deletions applications/openshift/api-server/var_api_min_request_timeout.var
Original file line number Diff line number Diff line change
@@ -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"
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
documentation_complete: true

prodtype: ocp4

title: 'Ensure Eviction threshold Settings Are Set - evictionSoft: memory.available'

description: |-
<p>Two types of garbage collection are performed on an OpenShift Container Platform node:</p>

<ul>
<li>Container garbage collection: Removes terminated containers.</li>
<li>Image garbage collection: Removes images not referenced by any running pods.</li>
</ul>

<p>
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.
</p>

<p>
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:
</p>

<ul>
<li>soft eviction for containers</li>
<li>hard eviction for containers</li>
<li>eviction for images</li>
</ul>

<p>
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") }}}
</p>

<p>
This rule pertains to the <tt>memory.available</tt> setting of the <tt>evictionSoft</tt>
section.
</p>

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: '<tt>memory.available</tt> is not set in <tt>evictionSoft</tt> section'

ocil: |-
Run the following command on the kubelet node(s):
<pre>$ oc debug -q node/$NODE -- jq -r '.evictionSoft."memory.available"' /host/etc/kubernetes/kubelet.conf</pre>
and make sure it outputs
<pre>{{{ xccdf_value("var_kubelet_evictionsoft_memory_available") }}}</pre>

template:
name: yamlfile_value
vars:
filepath: /etc/kubernetes/kubelet.conf
yamlpath: ".evictionSoft['memory.available']"
xccdf_variable: var_kubelet_evictionsoft_memory_available
Original file line number Diff line number Diff line change
@@ -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
11 changes: 10 additions & 1 deletion docs/manual/developer/06_contributing_with_content.md
Original file line number Diff line number Diff line change
Expand Up @@ -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---)) -
Expand Down
3 changes: 3 additions & 0 deletions ocp4/profiles/cis-node.profile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
###
Expand Down
3 changes: 1 addition & 2 deletions ocp4/profiles/cis.profile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 0 additions & 1 deletion shared/references/cce-redhat-avail.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 37 additions & 1 deletion shared/templates/yamlfile_value/oval.template
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,39 @@
<literal_component>{{{ FILEPATH }}}</literal_component>
{{% endif %}}
</local_variable>

{{% if not XCCDF_VARIABLE or (XCCDF_VARIABLE and not EMBEDDED_DATA) %}}
<ind:yamlfilecontent_test id="test_{{{ rule_id }}}" check="all" check_existence="{{{ CHECK_EXISTENCE|default("only_one_exists") }}}"
{{{ {'comment': "In the file '" + FILEPATH + "' find only one object at path '" + YAMLPATH + "'."}|xmlattr }}} version="1">
<ind:object object_ref="object_{{{ rule_id }}}"/>
<ind:state state_ref="state_{{{ rule_id }}}"/>
</ind:yamlfilecontent_test>
{{% else %}}
<ind:variable_test id="test_{{{ rule_id }}}" check="all" check_existence="all_exist" comment="comment1" version="1">
<ind:object object_ref="variable_object_{{{ rule_id }}}" />
<ind:state state_ref="variable_state_{{{ rule_id }}}" />
</ind:variable_test>

<ind:variable_object id="variable_object_{{{ rule_id }}}" version="1">
<ind:var_ref>local_variable_{{{ rule_id }}}</ind:var_ref>
</ind:variable_object>

<ind:variable_state id="variable_state_{{{ rule_id }}}" version="1">
<ind:value datatype="string" operation="equals" var_ref="{{{ XCCDF_VARIABLE }}}"/>
</ind:variable_state>

{{% for val in VALUES %}}
<local_variable id="local_variable_{{{ rule_id }}}" datatype="string" comment="comment1" version="1">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may not work with multiple values.
It seems to me that there will be multiple local_variable with the same ID.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh! this might need an enhancement then.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it doesn't make sense to keep this multiple value option here. We should consider only the first element and make sure in the template data processing that the condition is met. Partially, this condition is already met... when using variables and embedded the data processing checks if values is set, I think we would have to expand to check if only a single value is present

<regex_capture pattern='{{{ val.value }}}'>
<object_component item_field="value" record_field="#" object_ref="object_{{{ rule_id }}}" />
</regex_capture>
</local_variable>
{{% endfor %}}

{{% endif %}}

{{% if XCCDF_VARIABLE %}}
<external_variable comment="variable" datatype="string" id="{{{ XCCDF_VARIABLE }}}" version="1" />
{{% endif %}}

{{% if OCP_DATA %}}
<unix:file_test id="test_file_for_{{{ rule_id }}}" check="all" check_existence="only_one_exists"
Expand All @@ -48,17 +75,26 @@
<ind:yamlpath>{{{ YAMLPATH }}}</ind:yamlpath>
</ind:yamlfilecontent_object>

{{% if not XCCDF_VARIABLE or (XCCDF_VARIABLE and not EMBEDDED_DATA) %}}
<ind:yamlfilecontent_state id="state_{{{ rule_id }}}" version="1">
<ind:value datatype="record"{{% if ENTITY_CHECK %}} entity_check="{{{ ENTITY_CHECK }}}"{{% endif %}}>
{{% 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") %}}
<field {{{ {'name': name, 'datatype': datatype, 'operation': 'equals'}|xmlattr }}} var_ref="{{{ XCCDF_VARIABLE }}}" />
{{% else %}}
{{% for val in VALUES %}}
<field {{{ {'name': val.key|default("#")|escape_yaml_key, 'datatype': val.type, 'operation': val.operation, 'entity_check': val.entity_check}|xmlattr }}}>{{{ val.value }}}</field>
{{% endfor %}}
{{% endif %}}
</ind:value>
</ind:yamlfilecontent_state>
{{% endif %}}

{{% if OCP_DATA %}}
<external_variable comment="Root of OCP data dump" datatype="string" id="ocp_data_root" version="1" />
{{% endif %}}

</def-group>
{{% endif %}}

9 changes: 9 additions & 0 deletions shared/templates/yamlfile_value/template.py
Original file line number Diff line number Diff line change
@@ -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